Merge tag 'at91-5.4-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux...
authorArnd Bergmann <arnd@arndb.de>
Tue, 3 Sep 2019 14:12:52 +0000 (16:12 +0200)
committerArnd Bergmann <arnd@arndb.de>
Tue, 3 Sep 2019 14:12:53 +0000 (16:12 +0200)
AT91 DT for 5.4

 - style cleanup for at91sam9x5 based boards
 - avoid colliding node and property names

* tag 'at91-5.4-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux:
  ARM: dts: at91: at91sam9x5dm.dtsi: Style cleanup
  ARM: dts: at91: at91sam9x5_lcd.dtsi: Style cleanup
  ARM: dts: at91: at91sam9xx5ek: Style cleanup
  ARM: dts: at91: at91sam9g15: Style cleanup
  ARM: dts: at91: kizboxmini: Style cleanup
  ARM: dts: at91: cosino: Style cleanup
  ARM: dts: at91: ariettag25: style cleanup
  ARM: dts: at91: ariag25: Style cleanup
  ARM: dts: at91: Add label for sam9x5's internal RTC
  dt-bindings: add vendor prefix "acme" for "Acme Systems srl"
  ARM: dts: at91: Avoid colliding 'display' node and property names

Link: https://lore.kernel.org/r/20190825202642.GA18853@piout.net
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1707 files changed:
.gitignore
.mailmap
Documentation/PCI/pci-error-recovery.rst
Documentation/RCU/rculist_nulls.txt
Documentation/admin-guide/conf.py [deleted file]
Documentation/admin-guide/hw-vuln/spectre.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/mm/transhuge.rst
Documentation/conf.py
Documentation/core-api/conf.py [deleted file]
Documentation/crypto/conf.py [deleted file]
Documentation/dev-tools/conf.py [deleted file]
Documentation/devicetree/bindings/arm/amlogic.yaml
Documentation/devicetree/bindings/arm/fsl.yaml
Documentation/devicetree/bindings/arm/idle-states.txt
Documentation/devicetree/bindings/arm/mediatek.yaml
Documentation/devicetree/bindings/arm/renesas.yaml
Documentation/devicetree/bindings/arm/rockchip.yaml
Documentation/devicetree/bindings/arm/socionext/milbeaut.yaml
Documentation/devicetree/bindings/arm/sunxi.yaml
Documentation/devicetree/bindings/arm/ti/ti,davinci.yaml
Documentation/devicetree/bindings/bus/imx-weim.txt
Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
Documentation/devicetree/bindings/clock/imx8mn-clock.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/eeprom/at25.txt
Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
Documentation/devicetree/bindings/iio/accel/adi,adxl345.yaml
Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml
Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/amazon,al-fic.txt
Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
Documentation/devicetree/bindings/media/amlogic,vdec.txt
Documentation/devicetree/bindings/media/rcar_imr.txt [deleted file]
Documentation/devicetree/bindings/media/rcar_vin.txt [deleted file]
Documentation/devicetree/bindings/media/renesas,csi2.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/renesas,imr.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt [deleted file]
Documentation/devicetree/bindings/media/renesas,vin.txt [new file with mode: 0644]
Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt [deleted file]
Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/sun4i-gpadc.txt [deleted file]
Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml [deleted file]
Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
Documentation/devicetree/bindings/net/can/rcar_can.txt
Documentation/devicetree/bindings/net/can/rcar_canfd.txt
Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/nvmem/nvmem.txt
Documentation/devicetree/bindings/nvmem/nvmem.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
Documentation/devicetree/bindings/riscv/cpus.txt [deleted file]
Documentation/devicetree/bindings/riscv/cpus.yaml
Documentation/devicetree/bindings/riscv/sifive.yaml
Documentation/devicetree/bindings/serial/fsl-lpuart.txt
Documentation/devicetree/bindings/serial/mtk-uart.txt
Documentation/devicetree/bindings/spi/spi-controller.yaml
Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
Documentation/devicetree/bindings/usb/usb251xb.txt
Documentation/devicetree/bindings/vendor-prefixes.yaml
Documentation/doc-guide/conf.py [deleted file]
Documentation/driver-api/80211/conf.py [deleted file]
Documentation/driver-api/conf.py [deleted file]
Documentation/driver-api/generic-counter.rst
Documentation/driver-api/phy/phy.rst
Documentation/driver-api/pm/conf.py [deleted file]
Documentation/filesystems/cifs/TODO
Documentation/filesystems/conf.py [deleted file]
Documentation/gpu/conf.py [deleted file]
Documentation/hwmon/k8temp.rst
Documentation/index.rst
Documentation/input/conf.py [deleted file]
Documentation/kernel-hacking/conf.py [deleted file]
Documentation/locking/spinlocks.rst
Documentation/maintainer/conf.py [deleted file]
Documentation/media/conf.py [deleted file]
Documentation/memory-barriers.txt
Documentation/networking/conf.py [deleted file]
Documentation/networking/tls-offload.rst
Documentation/power/index.rst
Documentation/powerpc/DAWR-POWER9.txt [deleted file]
Documentation/powerpc/bootwrapper.rst [new file with mode: 0644]
Documentation/powerpc/bootwrapper.txt [deleted file]
Documentation/powerpc/cpu_families.rst [new file with mode: 0644]
Documentation/powerpc/cpu_families.txt [deleted file]
Documentation/powerpc/cpu_features.rst [new file with mode: 0644]
Documentation/powerpc/cpu_features.txt [deleted file]
Documentation/powerpc/cxl.rst [new file with mode: 0644]
Documentation/powerpc/cxl.txt [deleted file]
Documentation/powerpc/cxlflash.rst [new file with mode: 0644]
Documentation/powerpc/cxlflash.txt [deleted file]
Documentation/powerpc/dawr-power9.rst [new file with mode: 0644]
Documentation/powerpc/dscr.rst [new file with mode: 0644]
Documentation/powerpc/dscr.txt [deleted file]
Documentation/powerpc/eeh-pci-error-recovery.rst [new file with mode: 0644]
Documentation/powerpc/eeh-pci-error-recovery.txt [deleted file]
Documentation/powerpc/firmware-assisted-dump.rst [new file with mode: 0644]
Documentation/powerpc/firmware-assisted-dump.txt [deleted file]
Documentation/powerpc/hvcs.rst [new file with mode: 0644]
Documentation/powerpc/hvcs.txt [deleted file]
Documentation/powerpc/index.rst [new file with mode: 0644]
Documentation/powerpc/isa-versions.rst
Documentation/powerpc/mpc52xx.rst [new file with mode: 0644]
Documentation/powerpc/mpc52xx.txt [deleted file]
Documentation/powerpc/pci_iov_resource_on_powernv.rst [new file with mode: 0644]
Documentation/powerpc/pci_iov_resource_on_powernv.txt [deleted file]
Documentation/powerpc/pmu-ebb.rst [new file with mode: 0644]
Documentation/powerpc/pmu-ebb.txt [deleted file]
Documentation/powerpc/ptrace.rst [new file with mode: 0644]
Documentation/powerpc/ptrace.txt [deleted file]
Documentation/powerpc/qe_firmware.rst [new file with mode: 0644]
Documentation/powerpc/qe_firmware.txt [deleted file]
Documentation/powerpc/syscall64-abi.rst [new file with mode: 0644]
Documentation/powerpc/syscall64-abi.txt [deleted file]
Documentation/powerpc/transactional_memory.rst [new file with mode: 0644]
Documentation/powerpc/transactional_memory.txt [deleted file]
Documentation/process/conf.py [deleted file]
Documentation/process/deprecated.rst
Documentation/s390/vfio-ccw.rst
Documentation/sh/conf.py [deleted file]
Documentation/sound/conf.py [deleted file]
Documentation/sphinx/load_config.py
Documentation/translations/it_IT/doc-guide/sphinx.rst
Documentation/translations/it_IT/process/index.rst
Documentation/translations/it_IT/process/kernel-docs.rst
Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
Documentation/translations/it_IT/process/programming-language.rst [new file with mode: 0644]
Documentation/translations/ko_KR/memory-barriers.txt
Documentation/userspace-api/conf.py [deleted file]
Documentation/virt/index.rst [new file with mode: 0644]
Documentation/virt/kvm/amd-memory-encryption.rst [new file with mode: 0644]
Documentation/virt/kvm/api.txt [new file with mode: 0644]
Documentation/virt/kvm/arm/hyp-abi.txt [new file with mode: 0644]
Documentation/virt/kvm/arm/psci.txt [new file with mode: 0644]
Documentation/virt/kvm/cpuid.rst [new file with mode: 0644]
Documentation/virt/kvm/devices/README [new file with mode: 0644]
Documentation/virt/kvm/devices/arm-vgic-its.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/arm-vgic-v3.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/arm-vgic.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/mpic.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/s390_flic.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/vcpu.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/vfio.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/vm.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/xics.txt [new file with mode: 0644]
Documentation/virt/kvm/devices/xive.txt [new file with mode: 0644]
Documentation/virt/kvm/halt-polling.txt [new file with mode: 0644]
Documentation/virt/kvm/hypercalls.txt [new file with mode: 0644]
Documentation/virt/kvm/index.rst [new file with mode: 0644]
Documentation/virt/kvm/locking.txt [new file with mode: 0644]
Documentation/virt/kvm/mmu.txt [new file with mode: 0644]
Documentation/virt/kvm/msr.txt [new file with mode: 0644]
Documentation/virt/kvm/nested-vmx.txt [new file with mode: 0644]
Documentation/virt/kvm/ppc-pv.txt [new file with mode: 0644]
Documentation/virt/kvm/review-checklist.txt [new file with mode: 0644]
Documentation/virt/kvm/s390-diag.txt [new file with mode: 0644]
Documentation/virt/kvm/timekeeping.txt [new file with mode: 0644]
Documentation/virt/kvm/vcpu-requests.rst [new file with mode: 0644]
Documentation/virt/paravirt_ops.rst [new file with mode: 0644]
Documentation/virt/uml/UserModeLinux-HOWTO.txt [new file with mode: 0644]
Documentation/virtual/index.rst [deleted file]
Documentation/virtual/kvm/amd-memory-encryption.rst [deleted file]
Documentation/virtual/kvm/api.txt [deleted file]
Documentation/virtual/kvm/arm/hyp-abi.txt [deleted file]
Documentation/virtual/kvm/arm/psci.txt [deleted file]
Documentation/virtual/kvm/cpuid.rst [deleted file]
Documentation/virtual/kvm/devices/README [deleted file]
Documentation/virtual/kvm/devices/arm-vgic-its.txt [deleted file]
Documentation/virtual/kvm/devices/arm-vgic-v3.txt [deleted file]
Documentation/virtual/kvm/devices/arm-vgic.txt [deleted file]
Documentation/virtual/kvm/devices/mpic.txt [deleted file]
Documentation/virtual/kvm/devices/s390_flic.txt [deleted file]
Documentation/virtual/kvm/devices/vcpu.txt [deleted file]
Documentation/virtual/kvm/devices/vfio.txt [deleted file]
Documentation/virtual/kvm/devices/vm.txt [deleted file]
Documentation/virtual/kvm/devices/xics.txt [deleted file]
Documentation/virtual/kvm/devices/xive.txt [deleted file]
Documentation/virtual/kvm/halt-polling.txt [deleted file]
Documentation/virtual/kvm/hypercalls.txt [deleted file]
Documentation/virtual/kvm/index.rst [deleted file]
Documentation/virtual/kvm/locking.txt [deleted file]
Documentation/virtual/kvm/mmu.txt [deleted file]
Documentation/virtual/kvm/msr.txt [deleted file]
Documentation/virtual/kvm/nested-vmx.txt [deleted file]
Documentation/virtual/kvm/ppc-pv.txt [deleted file]
Documentation/virtual/kvm/review-checklist.txt [deleted file]
Documentation/virtual/kvm/s390-diag.txt [deleted file]
Documentation/virtual/kvm/timekeeping.txt [deleted file]
Documentation/virtual/kvm/vcpu-requests.rst [deleted file]
Documentation/virtual/paravirt_ops.rst [deleted file]
Documentation/virtual/uml/UserModeLinux-HOWTO.txt [deleted file]
Documentation/vm/conf.py [deleted file]
Documentation/vm/hmm.rst
Documentation/watchdog/hpwdt.rst
Documentation/x86/conf.py [deleted file]
MAINTAINERS
Makefile
arch/arm/Kconfig.debug
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-boneblue.dts
arch/arm/boot/dts/am335x-cm-t335.dts
arch/arm/boot/dts/aspeed-ast2500-evb.dts
arch/arm/boot/dts/aspeed-bmc-facebook-minipack.dts [new file with mode: 0644]
arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts
arch/arm/boot/dts/aspeed-bmc-facebook-wedge100.dts [new file with mode: 0644]
arch/arm/boot/dts/aspeed-bmc-facebook-wedge40.dts [new file with mode: 0644]
arch/arm/boot/dts/aspeed-bmc-inspur-fp5280g2.dts
arch/arm/boot/dts/aspeed-bmc-lenovo-hr855xg2.dts [new file with mode: 0644]
arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts [new file with mode: 0755]
arch/arm/boot/dts/aspeed-bmc-opp-swift.dts
arch/arm/boot/dts/aspeed-g4.dtsi
arch/arm/boot/dts/aspeed-g5.dtsi
arch/arm/boot/dts/bcm47094-linksys-panamera.dts
arch/arm/boot/dts/ep7211-edb7211.dts
arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5800.dtsi
arch/arm/boot/dts/gemini-nas4220b.dts
arch/arm/boot/dts/gemini-sl93512r.dts
arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
arch/arm/boot/dts/imx25-pdk.dts
arch/arm/boot/dts/imx27-apf27dev.dts
arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
arch/arm/boot/dts/imx53-m53menlo.dts
arch/arm/boot/dts/imx6qdl-colibri.dtsi
arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
arch/arm/boot/dts/imx6qdl-wandboard.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/boot/dts/imx6sll.dtsi
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
arch/arm/boot/dts/imx6ul-geam.dts
arch/arm/boot/dts/imx6ul-isiot.dtsi
arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-kontron-n6310-som.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-opos6uldev.dts
arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi [deleted file]
arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi [deleted file]
arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts [deleted file]
arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi [deleted file]
arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-phytec-segin.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-pico-hobbit.dts
arch/arm/boot/dts/imx6ul-pico-pi.dts
arch/arm/boot/dts/imx6ul.dtsi
arch/arm/boot/dts/imx6ull-phytec-phycore-som.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-emmc.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6ull-phytec-segin-ff-rdk-nand.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6ull-phytec-segin-lc-rdk-nand.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6ull-phytec-segin-peb-eval-01.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ull-phytec-segin.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx7-colibri.dtsi
arch/arm/boot/dts/imx7d-cl-som-imx7.dts
arch/arm/boot/dts/imx7d-zii-rmu2.dts [new file with mode: 0644]
arch/arm/boot/dts/imx7d-zii-rpu2.dts
arch/arm/boot/dts/imx7d.dtsi
arch/arm/boot/dts/imx7s.dtsi
arch/arm/boot/dts/imx7ulp.dtsi
arch/arm/boot/dts/meson8b-ec100.dts
arch/arm/boot/dts/meson8b-mxq.dts
arch/arm/boot/dts/meson8b-odroidc1.dts
arch/arm/boot/dts/meson8b.dtsi
arch/arm/boot/dts/mt7629-rfb.dts [new file with mode: 0644]
arch/arm/boot/dts/mt7629.dtsi [new file with mode: 0644]
arch/arm/boot/dts/nspire-classic.dtsi
arch/arm/boot/dts/nspire-cx.dts
arch/arm/boot/dts/nspire.dtsi
arch/arm/boot/dts/omap3-gta04.dtsi
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/r8a77470.dtsi
arch/arm/boot/dts/r8a7779.dtsi
arch/arm/boot/dts/rk3036.dtsi
arch/arm/boot/dts/rk3229-xms6.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3288-evb.dtsi
arch/arm/boot/dts/rk3288-tinker.dtsi
arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
arch/arm/boot/dts/rk3288-veyron-edp.dtsi [new file with mode: 0644]
arch/arm/boot/dts/rk3288-veyron-fievel.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3288-veyron-jaq.dts
arch/arm/boot/dts/rk3288-veyron-jerry.dts
arch/arm/boot/dts/rk3288-veyron-minnie.dts
arch/arm/boot/dts/rk3288-veyron-pinky.dts
arch/arm/boot/dts/rk3288-veyron-speedy.dts
arch/arm/boot/dts/rk3288-veyron-tiger.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3288-veyron.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/socfpga_arria10.dtsi
arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/ste-href-stuib.dtsi
arch/arm/boot/dts/ste-nomadik-nhk15.dts
arch/arm/boot/dts/ste-snowball.dts
arch/arm/boot/dts/stm32429i-eval.dts
arch/arm/boot/dts/stm32f429.dtsi
arch/arm/boot/dts/stm32f746.dtsi
arch/arm/boot/dts/stm32h743i-eval.dts
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
arch/arm/boot/dts/stm32mp157a-dk1.dts
arch/arm/boot/dts/stm32mp157c-ed1.dts
arch/arm/boot/dts/stm32mp157c-ev1.dts
arch/arm/boot/dts/stm32mp157c.dtsi
arch/arm/boot/dts/sun4i-a10-a1000.dts
arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
arch/arm/boot/dts/sun4i-a10-cubieboard.dts
arch/arm/boot/dts/sun4i-a10-hackberry.dts
arch/arm/boot/dts/sun4i-a10-itead-iteaduino-plus.dts
arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
arch/arm/boot/dts/sun4i-a10-marsboard.dts
arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
arch/arm/boot/dts/sun4i-a10-pcduino.dts
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
arch/arm/boot/dts/sun5i-a13-q8-tablet.dts
arch/arm/boot/dts/sun5i.dtsi
arch/arm/boot/dts/sun6i-a31-colombus.dts
arch/arm/boot/dts/sun6i-a31-hummingbird.dts
arch/arm/boot/dts/sun6i-a31-i7.dts
arch/arm/boot/dts/sun6i-a31-m9.dts
arch/arm/boot/dts/sun6i-a31-mele-a1000g-quad.dts
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun6i-a31s-cs908.dts
arch/arm/boot/dts/sun6i-a31s-sina31s.dts
arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts
arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
arch/arm/boot/dts/sun7i-a20-bananapi.dts
arch/arm/boot/dts/sun7i-a20-bananapro.dts
arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
arch/arm/boot/dts/sun7i-a20-cubietruck.dts
arch/arm/boot/dts/sun7i-a20-hummingbird.dts
arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
arch/arm/boot/dts/sun7i-a20-icnova-swac.dts
arch/arm/boot/dts/sun7i-a20-itead-ibox.dts
arch/arm/boot/dts/sun7i-a20-lamobo-r1.dts
arch/arm/boot/dts/sun7i-a20-m3.dts
arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts
arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
arch/arm/boot/dts/sun7i-a20-orangepi-mini.dts
arch/arm/boot/dts/sun7i-a20-orangepi.dts
arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts
arch/arm/boot/dts/sun7i-a20-pcduino3.dts
arch/arm/boot/dts/sun7i-a20-wits-pro-a20-dkt.dts
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a23-a33.dtsi
arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
arch/arm/boot/dts/sun8i-a83t.dtsi
arch/arm/boot/dts/sun8i-r40.dtsi
arch/arm/boot/dts/sun8i-s3-lichee-zero-plus.dts [new file with mode: 0644]
arch/arm/boot/dts/sun8i-v3.dtsi [new file with mode: 0644]
arch/arm/boot/dts/sun8i-v3s.dtsi
arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
arch/arm/boot/dts/sun9i-a80-optimus.dts
arch/arm/boot/dts/sun9i-a80.dtsi
arch/arm/boot/dts/sunxi-h3-h5.dtsi
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
arch/arm/boot/dts/vexpress-v2m.dtsi
arch/arm/boot/dts/vf610-zii-cfu1.dts
arch/arm/boot/dts/vf610-zii-scu4-aib.dts
arch/arm/boot/dts/vf610-zii-spb4.dts
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/dma-mapping.h
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/signal.c
arch/arm/kvm/coproc.c
arch/arm/mach-davinci/sleep.S
arch/arm/mach-ep93xx/crunch.c
arch/arm/mach-netx/Kconfig [deleted file]
arch/arm/mach-netx/Makefile [deleted file]
arch/arm/mach-netx/Makefile.boot [deleted file]
arch/arm/mach-netx/fb.c [deleted file]
arch/arm/mach-netx/fb.h [deleted file]
arch/arm/mach-netx/generic.c [deleted file]
arch/arm/mach-netx/generic.h [deleted file]
arch/arm/mach-netx/include/mach/hardware.h [deleted file]
arch/arm/mach-netx/include/mach/irqs.h [deleted file]
arch/arm/mach-netx/include/mach/netx-regs.h [deleted file]
arch/arm/mach-netx/include/mach/pfifo.h [deleted file]
arch/arm/mach-netx/include/mach/uncompress.h [deleted file]
arch/arm/mach-netx/include/mach/xc.h [deleted file]
arch/arm/mach-netx/nxdb500.c [deleted file]
arch/arm/mach-netx/nxdkn.c [deleted file]
arch/arm/mach-netx/nxeb500hmi.c [deleted file]
arch/arm/mach-netx/pfifo.c [deleted file]
arch/arm/mach-netx/time.c [deleted file]
arch/arm/mach-netx/xc.c [deleted file]
arch/arm/mach-tegra/reset.c
arch/arm/mm/Kconfig
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/plat-omap/dma.c
arch/arm64/Makefile
arch/arm64/boot/dts/allwinner/Makefile
arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts
arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
arch/arm64/boot/dts/allwinner/sun50i-h6-tanix-tx6.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
arch/arm64/boot/dts/amlogic/Makefile
arch/arm64/boot/dts/amlogic/meson-axg.dtsi
arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dts
arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-g12b.dtsi
arch/arm64/boot/dts/amlogic/meson-gx.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-sm1.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/arm/fvp-base-revc.dts
arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
arch/arm64/boot/dts/freescale/Makefile
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
arch/arm64/boot/dts/freescale/imx8mm-evk.dts
arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
arch/arm64/boot/dts/freescale/imx8mm.dtsi
arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mn.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-evk.dts
arch/arm64/boot/dts/freescale/imx8mq-hummingboard-pulse.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
arch/arm64/boot/dts/freescale/imx8mq-nitrogen.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-pico-pi.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-sr-som.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/freescale/imx8qxp-ai_ml.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
arch/arm64/boot/dts/freescale/imx8qxp.dtsi
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
arch/arm64/boot/dts/mediatek/mt8183-evb.dts
arch/arm64/boot/dts/mediatek/mt8183.dtsi
arch/arm64/boot/dts/renesas/hihope-common.dtsi
arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
arch/arm64/boot/dts/renesas/r8a774a1.dtsi
arch/arm64/boot/dts/renesas/r8a774c0-cat874.dts
arch/arm64/boot/dts/renesas/r8a774c0.dtsi
arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
arch/arm64/boot/dts/renesas/r8a7795.dtsi
arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
arch/arm64/boot/dts/renesas/r8a7796.dtsi
arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
arch/arm64/boot/dts/renesas/r8a77965.dtsi
arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
arch/arm64/boot/dts/renesas/r8a77970.dtsi
arch/arm64/boot/dts/renesas/r8a77980-condor.dts
arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
arch/arm64/boot/dts/renesas/r8a77980.dtsi
arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
arch/arm64/boot/dts/renesas/r8a77990.dtsi
arch/arm64/boot/dts/renesas/r8a77995-draak.dts
arch/arm64/boot/dts/renesas/r8a77995.dtsi
arch/arm64/boot/dts/renesas/salvator-common.dtsi
arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
arch/arm64/boot/dts/renesas/ulcb.dtsi
arch/arm64/boot/dts/rockchip/Makefile
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/daifflags.h
arch/arm64/include/asm/efi.h
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/ptrace.h
arch/arm64/include/asm/stacktrace.h
arch/arm64/include/asm/vdso/compat_gettimeofday.h
arch/arm64/include/uapi/asm/bpf_perf_event.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kernel/module.c
arch/arm64/kernel/perf_callchain.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/process.c
arch/arm64/kernel/return_address.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/stacktrace.c
arch/arm64/kernel/time.c
arch/arm64/kernel/traps.c
arch/arm64/kernel/vdso/Makefile
arch/arm64/kernel/vdso32/Makefile
arch/arm64/kvm/hyp/debug-sr.c
arch/arm64/kvm/regmap.c
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/fault.c
arch/csky/include/uapi/asm/byteorder.h
arch/csky/include/uapi/asm/cachectl.h
arch/csky/include/uapi/asm/perf_regs.h
arch/csky/include/uapi/asm/ptrace.h
arch/csky/include/uapi/asm/sigcontext.h
arch/csky/include/uapi/asm/unistd.h
arch/mips/cavium-octeon/octeon-usb.c
arch/mips/kernel/cacheinfo.c
arch/mips/kernel/i8253.c
arch/mips/kvm/emulate.c
arch/mips/kvm/mips.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/ops-bcm63xx.c
arch/mips/vdso/vdso.h
arch/nds32/include/uapi/asm/auxvec.h
arch/nds32/include/uapi/asm/byteorder.h
arch/nds32/include/uapi/asm/cachectl.h
arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
arch/nds32/include/uapi/asm/param.h
arch/nds32/include/uapi/asm/ptrace.h
arch/nds32/include/uapi/asm/sigcontext.h
arch/nds32/include/uapi/asm/unistd.h
arch/parisc/Makefile
arch/parisc/boot/compressed/Makefile
arch/parisc/boot/compressed/vmlinux.lds.S
arch/parisc/configs/default_defconfig [deleted file]
arch/parisc/configs/defconfig [new file with mode: 0644]
arch/parisc/include/asm/kprobes.h
arch/parisc/kernel/ftrace.c
arch/parisc/kernel/pacache.S
arch/parisc/math-emu/Makefile
arch/parisc/mm/fault.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/hvcall.h
arch/powerpc/include/asm/pmc.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/bpf_perf_event.h
arch/powerpc/include/uapi/asm/kvm_para.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/align.c
arch/powerpc/kernel/dma-common.c [new file with mode: 0644]
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/syscalls/syscall.tbl
arch/powerpc/kvm/book3s_32_mmu.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_xive.c
arch/powerpc/kvm/book3s_xive_native.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/book3s64/hash_utils.c
arch/powerpc/mm/kasan/kasan_init_32.c
arch/powerpc/mm/mem.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/sysdev/xive/common.c
arch/riscv/boot/dts/sifive/fu540-c000.dtsi
arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
arch/riscv/configs/defconfig
arch/riscv/include/asm/Kbuild
arch/riscv/include/uapi/asm/auxvec.h
arch/riscv/include/uapi/asm/bitsperlong.h
arch/riscv/include/uapi/asm/byteorder.h
arch/riscv/include/uapi/asm/hwcap.h
arch/riscv/include/uapi/asm/ptrace.h
arch/riscv/include/uapi/asm/sigcontext.h
arch/riscv/include/uapi/asm/ucontext.h
arch/riscv/include/uapi/asm/unistd.h
arch/riscv/kernel/vdso/Makefile
arch/riscv/lib/Makefile
arch/riscv/lib/delay.c
arch/riscv/lib/udivdi3.S [deleted file]
arch/s390/boot/Makefile
arch/s390/boot/boot.h
arch/s390/boot/head.S
arch/s390/boot/ipl_parm.c
arch/s390/boot/kaslr.c
arch/s390/boot/version.c [new file with mode: 0644]
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/hypfs/hypfs_vm.c
arch/s390/include/asm/bitops.h
arch/s390/include/asm/page.h
arch/s390/include/asm/qdio.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/unistd.h
arch/s390/include/uapi/asm/bpf_perf_event.h
arch/s390/include/uapi/asm/ipl.h
arch/s390/include/uapi/asm/zcrypt.h
arch/s390/kernel/dumpstack.c
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/machine_kexec_reloc.c
arch/s390/kernel/perf_cpum_cf_diag.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls/syscall.tbl
arch/s390/kernel/vdso.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/kvm-s390.c
arch/s390/lib/xor.c
arch/s390/mm/dump_pagetables.c
arch/s390/mm/fault.c
arch/s390/mm/gmap.c
arch/s390/mm/pgalloc.c
arch/s390/scripts/Makefile.chkbss
arch/sh/include/uapi/asm/setup.h
arch/sh/include/uapi/asm/types.h
arch/sparc/include/uapi/asm/oradax.h
arch/x86/boot/string.c
arch/x86/entry/calling.h
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/events/intel/core.c
arch/x86/events/intel/ds.c
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/vdso/gettimeofday.h
arch/x86/include/uapi/asm/byteorder.h
arch/x86/include/uapi/asm/hwcap2.h
arch/x86/include/uapi/asm/sigcontext32.h
arch/x86/include/uapi/asm/types.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mtrr/cyrix.c
arch/x86/kernel/head_64.S
arch/x86/kernel/hpet.c
arch/x86/kernel/kvm.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/stacktrace.c
arch/x86/kernel/sysfb_efi.c
arch/x86/kvm/debugfs.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/cpu.c
arch/x86/mm/fault.c
arch/x86/purgatory/Makefile
arch/x86/purgatory/purgatory.c
arch/x86/purgatory/string.c [deleted file]
arch/xtensa/kernel/coprocessor.S
block/bfq-iosched.c
block/blk-cgroup.c
block/blk-iolatency.c
block/blk-mq-sched.h
block/blk-mq.c
block/blk-rq-qos.c
block/blk-settings.c
block/genhd.c
drivers/acpi/arm64/iort.c
drivers/acpi/device_pm.c
drivers/acpi/nfit/core.c
drivers/acpi/nfit/nfit.h
drivers/acpi/scan.c
drivers/android/binder.c
drivers/ata/libahci_platform.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/libata-zpodd.c
drivers/ata/pata_rb532_cf.c
drivers/atm/iphase.c
drivers/base/core.c
drivers/base/firmware_loader/firmware.h
drivers/base/platform.c
drivers/block/aoe/aoedev.c
drivers/block/ataflop.c
drivers/block/drbd/drbd_receiver.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/bluetooth/hci_ath.c
drivers/bluetooth/hci_bcm.c
drivers/bluetooth/hci_intel.c
drivers/bluetooth/hci_ldisc.c
drivers/bluetooth/hci_mrvl.c
drivers/bluetooth/hci_qca.c
drivers/bluetooth/hci_uart.h
drivers/char/hpet.c
drivers/char/ipmi/ipmb_dev_int.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm1-cmd.c
drivers/char/tpm/tpm2-cmd.c
drivers/clk/at91/clk-generated.c
drivers/clk/clk.c
drivers/clk/imx/Kconfig
drivers/clk/imx/Makefile
drivers/clk/imx/clk-imx8mm.c
drivers/clk/imx/clk-imx8mn.c [new file with mode: 0644]
drivers/clk/imx/clk-imx8qxp-lpcg.c
drivers/clk/imx/clk.c
drivers/clk/imx/clk.h
drivers/clk/mediatek/clk-mt8183.c
drivers/clk/meson/Kconfig
drivers/clk/meson/Makefile
drivers/clk/meson/axg-aoclk.c
drivers/clk/meson/axg-audio.c
drivers/clk/meson/axg.c
drivers/clk/meson/clk-cpu-dyndiv.c [new file with mode: 0644]
drivers/clk/meson/clk-cpu-dyndiv.h [new file with mode: 0644]
drivers/clk/meson/clk-input.c [deleted file]
drivers/clk/meson/clk-input.h [deleted file]
drivers/clk/meson/clk-regmap.h
drivers/clk/meson/g12a-aoclk.c
drivers/clk/meson/g12a.c
drivers/clk/meson/g12a.h
drivers/clk/meson/gxbb-aoclk.c
drivers/clk/meson/gxbb.c
drivers/clk/meson/meson-aoclk.c
drivers/clk/meson/meson-aoclk.h
drivers/clk/meson/meson-eeclk.c
drivers/clk/meson/meson-eeclk.h
drivers/clk/meson/meson8b.c
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/sprd/Kconfig
drivers/clocksource/timer-riscv.c
drivers/connector/connector.c
drivers/cpufreq/pasemi-cpufreq.c
drivers/crypto/ccp/ccp-crypto-aes-galois.c
drivers/crypto/ccp/ccp-ops.c
drivers/crypto/ux500/cryp/cryp.c
drivers/firewire/core-device.c
drivers/firewire/core-iso.c
drivers/firewire/core-topology.c
drivers/firmware/Kconfig
drivers/firmware/iscsi_ibft.c
drivers/fpga/Kconfig
drivers/gpio/gpiolib.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dce120/dce120_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.c
drivers/gpu/drm/amd/display/dc/dsc/drm_dsc_dc.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
drivers/gpu/drm/amd/display/include/dpcd_defs.h
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/navi10_ppt.h
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/amd/powerplay/vega20_ppt.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/drm_client.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/exynos/exynos_drm_scaler.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_bios.c
drivers/gpu/drm/i915/display/intel_bw.c
drivers/gpu/drm/i915/display/intel_cdclk.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_vbt_defs.h
drivers/gpu/drm/i915/display/vlv_dsi_pll.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gem/i915_gem_mman.c
drivers/gpu/drm/i915/gem/i915_gem_pages.c
drivers/gpu/drm/i915/gem/i915_gem_pm.c
drivers/gpu/drm/i915/gem/i915_gem_userptr.c
drivers/gpu/drm/i915/gt/intel_context.c
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_engine_pm.c
drivers/gpu/drm/i915/gt/intel_engine_pm.h
drivers/gpu/drm/i915/gt/intel_engine_types.h
drivers/gpu/drm/i915/gt/intel_gt_pm.c
drivers/gpu/drm/i915/gt/intel_gt_pm.h
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_reset.c
drivers/gpu/drm/i915/gt/intel_ringbuffer.c
drivers/gpu/drm/i915/gt/intel_workarounds.c
drivers/gpu/drm/i915/gt/mock_engine.c
drivers/gpu/drm/i915/gt/selftest_reset.c
drivers/gpu/drm/i915/gt/selftest_workarounds.c
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/fb_decoder.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/trace_points.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_wakeref.h
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
drivers/hid/hid-a4tech.c
drivers/hid/hid-holtek-kbd.c
drivers/hid/hid-ids.h
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-quirks.c
drivers/hid/hid-sony.c
drivers/hid/hid-tmff.c
drivers/hid/usbhid/hiddev.c
drivers/hid/wacom_wac.c
drivers/hwmon/lm75.c
drivers/hwmon/nct6775.c
drivers/hwmon/nct7802.c
drivers/hwmon/occ/common.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/i2c/busses/i2c-at91-core.c
drivers/i2c/busses/i2c-at91-master.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-nvidia-gpu.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/iio/accel/cros_ec_accel_legacy.c
drivers/iio/adc/ingenic-adc.c
drivers/iio/adc/max9611.c
drivers/iio/adc/rcar-gyroadc.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/counters.c
drivers/infiniband/core/device.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/bnxt_re/qplib_res.h
drivers/infiniband/hw/bnxt_re/qplib_sp.c
drivers/infiniband/hw/bnxt_re/qplib_sp.h
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/rc.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hfi1/verbs.c
drivers/infiniband/hw/hns/Kconfig
drivers/infiniband/hw/hns/Makefile
drivers/infiniband/hw/hns/hns_roce_db.c
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/qedr/main.c
drivers/infiniband/sw/siw/siw_cm.c
drivers/infiniband/sw/siw/siw_main.c
drivers/infiniband/sw/siw/siw_qp.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/applespi.c
drivers/input/mouse/elantech.c
drivers/input/mouse/synaptics.c
drivers/input/tablet/kbtab.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/intel-iommu-debugfs.c
drivers/iommu/intel-iommu.c
drivers/iommu/iova.c
drivers/iommu/virtio-iommu.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-imx-gpcv2.c
drivers/irqchip/irq-mbigen.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/macintosh/smu.c
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/dm-table.c
drivers/media/platform/vivid/vivid-core.c
drivers/media/v4l2-core/v4l2-subdev.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/omap-usb-host.c
drivers/misc/eeprom/Kconfig
drivers/misc/eeprom/at24.c
drivers/misc/habanalabs/command_submission.c
drivers/misc/habanalabs/firmware_if.c
drivers/misc/habanalabs/goya/goya.c
drivers/misc/habanalabs/habanalabs.h
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/mmc/core/queue.c
drivers/mmc/host/cavium.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/meson-mx-sdio.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-of-at91.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci-sprd.c
drivers/mmc/host/sdhci-xenon.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/hyperbus/Kconfig
drivers/mtd/nand/onenand/onenand_base.c
drivers/mtd/nand/raw/nand_micron.c
drivers/net/arcnet/arc-rimi.c
drivers/net/arcnet/com20020-isa.c
drivers/net/arcnet/com90io.c
drivers/net/arcnet/com90xx.c
drivers/net/bonding/bond_main.c
drivers/net/can/at91_can.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/peak_canfd/peak_pciefd_main.c
drivers/net/can/rcar/rcar_canfd.c
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/spi/mcp251x.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/qca8k.c
drivers/net/dsa/sja1105/sja1105_dynamic_config.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/ethernet/8390/Kconfig
drivers/net/ethernet/agere/et131x.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/amd/Kconfig
drivers/net/ethernet/apple/Kconfig
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/chelsio/cxgb/my3126.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/enetc/Kconfig
drivers/net/ethernet/freescale/fman/fman.c
drivers/net/ethernet/google/gve/gve.h
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/google/gve/gve_rx.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mediatek/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/dev.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/params.h
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/port.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_flower.c
drivers/net/ethernet/mscc/ocelot_tc.c
drivers/net/ethernet/netronome/nfp/flower/offload.c
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/ni/Kconfig
drivers/net/ethernet/packetengines/Kconfig
drivers/net/ethernet/packetengines/Makefile
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_rdma.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/samsung/Kconfig
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/net/ethernet/xscale/Kconfig
drivers/net/hamradio/baycom_epp.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/fixed_phy.c
drivers/net/phy/mscc.c
drivers/net/phy/phy_device.c
drivers/net/phy/phy_led_triggers.c
drivers/net/phy/phylink.c
drivers/net/phy/sfp.c
drivers/net/ppp/pppoe.c
drivers/net/ppp/pppox.c
drivers/net/ppp/pptp.c
drivers/net/tun.c
drivers/net/usb/pegasus.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/vrf.c
drivers/net/wan/sdla.c
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.h
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/mwifiex/main.h
drivers/net/wireless/marvell/mwifiex/scan.c
drivers/net/wireless/ti/wlcore/vendor_cmd.c
drivers/nfc/nfcmrvl/main.c
drivers/nfc/nfcmrvl/uart.c
drivers/nfc/nfcmrvl/usb.c
drivers/nfc/st-nci/se.c
drivers/nfc/st21nfca/se.c
drivers/ntb/msi.c
drivers/nvdimm/btt_devs.c
drivers/nvdimm/bus.c
drivers/nvdimm/core.c
drivers/nvdimm/dimm_devs.c
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/nd-core.h
drivers/nvdimm/pfn_devs.c
drivers/nvdimm/pmem.c
drivers/nvdimm/region.c
drivers/nvdimm/region_devs.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvmem/nvmem-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/portdrv_core.c
drivers/pcmcia/db1xxx_ss.c
drivers/perf/arm_pmu.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
drivers/pinctrl/aspeed/pinctrl-aspeed.c
drivers/pinctrl/aspeed/pinmux-aspeed.c
drivers/pinctrl/aspeed/pinmux-aspeed.h
drivers/platform/olpc/olpc-xo175-ec.c
drivers/platform/x86/intel_pmc_core.c
drivers/platform/x86/pcengines-apuv2.c
drivers/powercap/intel_rapl_common.c
drivers/powercap/powercap_sys.c
drivers/pwm/core.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/lp87565-regulator.c
drivers/regulator/of_regulator.c
drivers/s390/block/dasd_alias.c
drivers/s390/char/con3215.c
drivers/s390/char/tape_core.c
drivers/s390/cio/qdio_main.c
drivers/s390/cio/vfio_ccw_async.c
drivers/s390/cio/vfio_ccw_cp.c
drivers/s390/cio/vfio_ccw_drv.c
drivers/s390/crypto/ap_queue.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/Kconfig
drivers/scsi/arm/fas216.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/fcoe/fcoe_ctlr.c
drivers/scsi/hpsa.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/scsi_lib.c
drivers/soc/fsl/qe/qe.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-fsl-qspi.c
drivers/spi/spi-gpio.c
drivers/spi/spi-pxa2xx.c
drivers/staging/android/ion/ion_page_pool.c
drivers/staging/fbtft/fb_bd663474.c
drivers/staging/fbtft/fb_ili9163.c
drivers/staging/fbtft/fb_ili9325.c
drivers/staging/fbtft/fb_s6d1121.c
drivers/staging/fbtft/fb_ssd1289.c
drivers/staging/fbtft/fb_ssd1331.c
drivers/staging/fbtft/fb_upd161704.c
drivers/staging/fbtft/fbtft-bus.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/gasket/apex_driver.c
drivers/staging/unisys/visornic/visornic_main.c
drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
drivers/target/iscsi/cxgbit/cxgbit_cm.c
drivers/target/iscsi/cxgbit/cxgbit_main.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/tty/hvc/hvcs.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/kgdboc.c
drivers/tty/serial/netx-serial.c [deleted file]
drivers/tty/tty_ldsem.c
drivers/tty/vt/vt.c
drivers/usb/core/devio.c
drivers/usb/core/hcd.c
drivers/usb/core/sysfs.c
drivers/usb/core/usb.h
drivers/usb/host/ehci-pci.c
drivers/usb/host/hwa-hc.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/pci-quirks.h
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-rcar.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/iowarrior.c
drivers/usb/misc/rio500.c
drivers/usb/misc/usb251xb.c
drivers/usb/misc/yurex.c
drivers/usb/storage/scsiglue.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi_ccg.c
drivers/vhost/vhost.h
drivers/video/fbdev/omap/omapfb_main.c
drivers/watchdog/ar7_wdt.c
drivers/watchdog/pcwd.c
drivers/watchdog/riowd.c
drivers/watchdog/sb_wdog.c
drivers/watchdog/scx200_wdt.c
drivers/watchdog/wdt.c
drivers/watchdog/wdt977.c
drivers/xen/gntdev.c
drivers/xen/privcmd.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-pciback/conf_space_capability.c
drivers/xen/xlate_mmu.c
fs/afs/fsclient.c
fs/afs/yfsclient.c
fs/block_dev.c
fs/btrfs/Kconfig
fs/btrfs/backref.c
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/locking.c
fs/btrfs/ordered-data.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/volumes.c
fs/cifs/connect.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/compat_ioctl.c
fs/coredump.c
fs/dax.c
fs/exec.c
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/super.c
fs/gfs2/bmap.c
fs/io_uring.c
fs/iomap/Makefile
fs/namespace.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/fscache.c
fs/nfs/fscache.h
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pnfs.c
fs/nfs/super.c
fs/ocfs2/xattr.c
fs/open.c
fs/super.c
fs/xfs/scrub/dabtree.c
fs/xfs/xfs_itable.c
include/asm-generic/futex.h
include/asm-generic/getorder.h
include/drm/drm_client.h
include/drm/drm_mode_config.h
include/dt-bindings/clock/g12a-clkc.h
include/dt-bindings/clock/imx8-clock.h
include/dt-bindings/clock/imx8mn-clock.h [new file with mode: 0644]
include/dt-bindings/reset/mt7629-resets.h [new file with mode: 0644]
include/kvm/arm_pmu.h
include/kvm/arm_vgic.h
include/linux/blk-cgroup.h
include/linux/blk_types.h
include/linux/ccp.h
include/linux/clk-provider.h
include/linux/clk.h
include/linux/connector.h
include/linux/cred.h
include/linux/device.h
include/linux/dim.h
include/linux/dma-mapping.h
include/linux/elevator.h
include/linux/filter.h
include/linux/fs.h
include/linux/gpio/consumer.h
include/linux/hmm.h
include/linux/if_pppox.h
include/linux/if_rmnet.h
include/linux/iova.h
include/linux/kvm_host.h
include/linux/mlx5/fs.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mod_devicetable.h
include/linux/netfilter/nf_conntrack_h323_asn1.h
include/linux/of.h
include/linux/page-flags-layout.h
include/linux/page-flags.h
include/linux/sched.h
include/linux/sched/numa_balancing.h
include/linux/skmsg.h
include/linux/wait.h
include/net/cfg80211.h
include/net/flow_offload.h
include/net/netfilter/nf_conntrack_expect.h
include/net/netfilter/nf_conntrack_synproxy.h
include/net/netfilter/nf_tables.h
include/net/pkt_cls.h
include/net/sch_generic.h
include/net/tc_act/tc_police.h
include/net/tc_act/tc_sample.h
include/net/tcp.h
include/net/tls.h
include/rdma/ib_verbs.h
include/rdma/rdmavt_qp.h
include/scsi/libfc.h
include/scsi/libfcoe.h
include/soc/fsl/qe/qe.h
include/sound/compress_driver.h
include/sound/simple_card_utils.h
include/sound/sof/control.h
include/sound/sof/dai-intel.h
include/sound/sof/dai.h
include/sound/sof/header.h
include/sound/sof/info.h
include/sound/sof/pm.h
include/sound/sof/stream.h
include/sound/sof/topology.h
include/sound/sof/trace.h
include/sound/sof/xtensa.h
include/trace/events/dma_fence.h
include/trace/events/napi.h
include/trace/events/qdisc.h
include/trace/events/tegra_apb_dma.h
include/uapi/linux/bpfilter.h
include/uapi/linux/ipmi_bmc.h
include/uapi/linux/isst_if.h
include/uapi/linux/kfd_ioctl.h
include/uapi/linux/kvm.h
include/uapi/linux/netfilter/nf_synproxy.h
include/uapi/linux/netfilter/xt_connlabel.h
include/uapi/linux/nl80211.h
include/uapi/linux/psp-sev.h
include/uapi/linux/rxrpc.h
include/uapi/linux/serial_core.h
include/uapi/linux/socket.h
include/uapi/linux/usb/g_uvc.h
include/uapi/linux/vbox_vmmdev_types.h
include/uapi/linux/vboxguest.h
include/uapi/linux/videodev2.h
include/uapi/linux/virtio_iommu.h
include/uapi/linux/virtio_pmem.h
include/uapi/linux/vmcore.h
include/uapi/linux/wmi.h
include/uapi/misc/fastrpc.h
include/uapi/rdma/rvt-abi.h
include/uapi/rdma/siw-abi.h
include/uapi/scsi/scsi_bsg_ufs.h
include/uapi/sound/skl-tplg-interface.h
include/uapi/sound/sof/fw.h
include/uapi/sound/sof/header.h
include/xen/xen-ops.h
kernel/Kconfig.preempt
kernel/Makefile
kernel/bpf/verifier.c
kernel/cred.c
kernel/dma/contiguous.c
kernel/dma/mapping.c
kernel/events/core.c
kernel/exit.c
kernel/fork.c
kernel/irq/affinity.c
kernel/locking/lockdep.c
kernel/locking/lockdep_proc.c
kernel/locking/mutex.c
kernel/locking/rwsem.c
kernel/memremap.c [deleted file]
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/signal.c
kernel/trace/trace_functions_graph.c
lib/Kconfig.kasan
lib/Makefile
lib/dim/dim.c
lib/dim/net_dim.c
lib/raid6/Makefile
lib/test_firmware.c
lib/test_meminit.c
lib/vdso/gettimeofday.c
mm/Makefile
mm/balloon_compaction.c
mm/compaction.c
mm/hmm.c
mm/kmemleak.c
mm/memory_hotplug.c
mm/memremap.c [new file with mode: 0644]
mm/migrate.c
mm/slub.c
mm/vmalloc.c
mm/vmscan.c
net/bridge/br.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_vlan.c
net/bridge/netfilter/Kconfig
net/bridge/netfilter/ebtables.c
net/bridge/netfilter/nft_meta_bridge.c
net/can/gw.c
net/core/dev.c
net/core/filter.c
net/core/flow_offload.c
net/core/skmsg.c
net/core/sock_map.c
net/dsa/slave.c
net/dsa/tag_sja1105.c
net/ipv4/inet_fragment.c
net/ipv4/ipip.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv4/netfilter/nf_nat_h323.c
net/ipv4/tcp_output.c
net/ipv4/tcp_ulp.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/netfilter/ip6t_rpfilter.c
net/ipv6/route.c
net/iucv/af_iucv.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/driver-ops.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/util.c
net/netfilter/Kconfig
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_ipmac.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/nf_conntrack_amanda.c
net/netfilter/nf_conntrack_broadcast.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_h323_asn1.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nf_conntrack_irc.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_pptp.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_conntrack_proto_icmp.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_sane.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_conntrack_tftp.c
net/netfilter/nf_nat_amanda.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_nat_ftp.c
net/netfilter/nf_nat_irc.c
net/netfilter/nf_nat_sip.c
net/netfilter/nf_nat_tftp.c
net/netfilter/nf_synproxy_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nfnetlink.c
net/netfilter/nft_chain_filter.c
net/netfilter/nft_chain_nat.c
net/netfilter/nft_ct.c
net/netfilter/nft_hash.c
net/netfilter/nft_meta.c
net/netfilter/nft_redir.c
net/netfilter/nft_synproxy.c
net/netrom/af_netrom.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/openvswitch/flow.h
net/openvswitch/flow_table.c
net/rds/rdma_transport.c
net/rxrpc/ar-internal.h
net/rxrpc/peer_event.c
net/rxrpc/peer_object.c
net/rxrpc/sendmsg.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_mirred.c
net/sched/act_mpls.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c
net/sched/cls_api.c
net/sched/cls_bpf.c
net/sched/cls_flower.c
net/sched/cls_matchall.c
net/sched/cls_u32.c
net/sched/sch_codel.c
net/sctp/socket.c
net/smc/af_smc.c
net/tipc/netlink_compat.c
net/tipc/socket.c
net/tipc/topsrv.c
net/tls/tls_main.c
net/tls/tls_sw.c
net/vmw_vsock/hyperv_transport.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/util.c
samples/vfio-mdev/mdpy-defs.h
scripts/Kbuild.include
scripts/Kconfig.include
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modpost
scripts/gen_compile_commands.py
scripts/headers_install.sh
scripts/kconfig/confdata.c
scripts/link-vmlinux.sh
scripts/sphinx-pre-install
security/Kconfig.hardening
security/selinux/ss/policydb.c
security/selinux/ss/sidtab.c
sound/ac97/bus.c
sound/core/compress_offload.c
sound/core/pcm_native.c
sound/firewire/packets-buffer.c
sound/hda/hdac_i915.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/codecs/cs42xx8.c
sound/soc/codecs/max98357a.c
sound/soc/codecs/max98373.c
sound/soc/codecs/max98373.h
sound/soc/codecs/pcm3060-i2c.c
sound/soc/codecs/pcm3060-spi.c
sound/soc/codecs/pcm3060.c
sound/soc/codecs/pcm3060.h
sound/soc/codecs/rt1011.c
sound/soc/codecs/rt1308.c [changed mode: 0755->0644]
sound/soc/codecs/rt1308.h [changed mode: 0755->0644]
sound/soc/generic/audio-graph-card.c
sound/soc/generic/simple-card-utils.c
sound/soc/generic/simple-card.c
sound/soc/intel/boards/bytcht_es8316.c
sound/soc/intel/common/soc-acpi-intel-bxt-match.c
sound/soc/intel/common/soc-acpi-intel-byt-match.c
sound/soc/intel/common/soc-acpi-intel-cht-match.c
sound/soc/intel/common/soc-acpi-intel-cnl-match.c
sound/soc/intel/common/soc-acpi-intel-glk-match.c
sound/soc/intel/common/soc-acpi-intel-hda-match.c
sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
sound/soc/intel/common/soc-acpi-intel-icl-match.c
sound/soc/intel/common/soc-acpi-intel-kbl-match.c
sound/soc/intel/common/soc-acpi-intel-skl-match.c
sound/soc/qcom/apq8016_sbc.c
sound/soc/rockchip/rockchip_i2s.c
sound/soc/rockchip/rockchip_max98090.c
sound/soc/samsung/odroid.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/sof/intel/cnl.c
sound/soc/sof/intel/hda-ipc.c
sound/soc/sunxi/sun4i-i2s.c
sound/soc/ti/davinci-mcasp.c
sound/sound_core.c
sound/usb/helper.c
sound/usb/hiface/pcm.c
sound/usb/line6/podhd.c
sound/usb/line6/variax.c
sound/usb/stream.c
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/mman.h
tools/arch/sparc/include/uapi/asm/mman.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/vmx.h
tools/include/uapi/asm-generic/mman-common.h
tools/include/uapi/asm-generic/mman.h
tools/include/uapi/asm-generic/unistd.h
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/if_link.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/sched.h
tools/include/uapi/linux/usbdevice_fs.h
tools/lib/bpf/btf.c
tools/lib/bpf/hashmap.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/xsk.c
tools/objtool/check.c
tools/objtool/check.h
tools/perf/Documentation/Makefile
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf.data-file-format.txt
tools/perf/arch/s390/util/machine.c
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/bench/numa.c
tools/perf/builtin-ftrace.c
tools/perf/builtin-probe.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/pmu-events/jevents.c
tools/perf/trace/beauty/usbdevfs_ioctl.sh
tools/perf/ui/browser.c
tools/perf/ui/tui/progress.c
tools/perf/util/annotate.c
tools/perf/util/cpumap.c
tools/perf/util/evsel.c
tools/perf/util/header.c
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/probe-event.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/stat-shadow.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/thread.c
tools/perf/util/zstd.c
tools/scripts/Makefile.include
tools/testing/ktest/config-bisect.pl
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/progs/sendmsg6_prog.c
tools/testing/selftests/bpf/test_xdp_vlan.sh
tools/testing/selftests/bpf/test_xdp_vlan_mode_generic.sh [new file with mode: 0755]
tools/testing/selftests/bpf/test_xdp_vlan_mode_native.sh [new file with mode: 0755]
tools/testing/selftests/bpf/verifier/ctx_skb.c
tools/testing/selftests/cgroup/cgroup_util.c
tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
tools/testing/selftests/kmod/kmod.sh
tools/testing/selftests/kselftest.h
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/config [new file with mode: 0644]
tools/testing/selftests/livepatch/functions.sh
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/forwarding/gre_multipath.sh
tools/testing/selftests/net/tls.c
tools/testing/selftests/pidfd/pidfd_test.c
tools/testing/selftests/tc-testing/tc-tests/actions/vlan.json
tools/testing/selftests/x86/test_vsyscall.c
usr/include/Makefile
virt/kvm/arm/arm.c
virt/kvm/arm/hyp/vgic-v3-sr.c
virt/kvm/arm/pmu.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.c
virt/kvm/arm/vgic/vgic.h
virt/kvm/kvm_main.c

index 8f5422c..2030c7a 100644 (file)
@@ -142,3 +142,6 @@ x509.genkey
 
 # Kdevelop4
 *.kdev4
+
+# Clang's compilation database file
+/compile_commands.json
index 0fef932..acba1a6 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -98,6 +98,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 +117,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 +134,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>
index 83db420..e5d450d 100644 (file)
@@ -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
+-------
index 8151f01..23f115d 100644 (file)
@@ -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/admin-guide/conf.py b/Documentation/admin-guide/conf.py
deleted file mode 100644 (file)
index 86f7389..0000000
+++ /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'),
-]
index 25f3b25..e05e581 100644 (file)
@@ -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
index 46b826f..47d981a 100644 (file)
                        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:
                                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]
                        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)
index 7ab93a8..bd57145 100644 (file)
@@ -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
index 3b2397b..a8fe845 100644 (file)
@@ -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 (file)
index db1f765..0000000
+++ /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 (file)
index 4335d25..0000000
+++ /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 (file)
index 7faafa3..0000000
+++ /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'),
-]
index 325c6fd..b48ea1e 100644 (file)
@@ -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,32 @@ 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 SoC
+        items:
+          - enum:
+              - seirobotics,sei610
+          - const: amlogic,sm1
 ...
index 7294ac3..1b4b4e6 100644 (file)
@@ -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
index 326f29b..2d325be 100644 (file)
@@ -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
index a4ad2eb..4043c50 100644 (file)
@@ -46,6 +46,10 @@ properties:
           - enum:
               - mediatek,mt6765-evb
           - const: mediatek,mt6765
+      - items:
+          - enum:
+              - mediatek,mt6779-evb
+          - const: mediatek,mt6779
       - items:
           - enum:
               - mediatek,mt6795-evb
index 08c923f..28eb458 100644 (file)
@@ -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
index 3486504..474f961 100644 (file)
@@ -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
index aae53fc..2bd519d 100644 (file)
@@ -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
index 000a00d..972b1e9 100644 (file)
@@ -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
index 4326d2c..a8765ba 100644 (file)
@@ -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
index dda7d6d..1b1d1c5 100644 (file)
@@ -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
index c935405..fa4d143 100644 (file)
@@ -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/imx8mn-clock.yaml b/Documentation/devicetree/bindings/clock/imx8mn-clock.yaml
new file mode 100644 (file)
index 0000000..622f365
--- /dev/null
@@ -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";
+    };
+
+...
index b3bde97..42577dd 100644 (file)
@@ -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"
index 8cb136c..4f0db8e 100644 (file)
@@ -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
index 001f2b7..c779000 100644 (file)
@@ -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
index 7ba167e..c602b6f 100644 (file)
@@ -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
index a7fafb9..e7daffe 100644 (file)
@@ -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/iio/adc/allwinner,sun8i-a33-ths.yaml b/Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml
new file mode 100644 (file)
index 0000000..d74962c
--- /dev/null
@@ -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>;
+    };
+
+...
index 4e82fd5..c676b03 100644 (file)
@@ -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>;
index bae10e2..507c141 100644 (file)
@@ -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
index 0e312fe..84ced3f 100644 (file)
@@ -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
index aabdd01..9b6aace 100644 (file)
@@ -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/rcar_imr.txt b/Documentation/devicetree/bindings/media/rcar_imr.txt
deleted file mode 100644 (file)
index b061415..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Renesas R-Car Image Renderer (Distortion Correction Engine)
------------------------------------------------------------
-
-The image renderer, or the distortion correction engine, is a drawing processor
-with a simple instruction system capable of referencing video capture data or
-data in an external memory as 2D texture data and performing texture mapping
-and drawing with respect to any shape that is split into triangular objects.
-
-Required properties:
-
-- compatible: "renesas,<soctype>-imr-lx4", "renesas,imr-lx4" as a fallback for
-  the image renderer light extended 4 (IMR-LX4) found in the R-Car gen3 SoCs,
-  where the examples with <soctype> are:
-  - "renesas,r8a7795-imr-lx4" for R-Car H3,
-  - "renesas,r8a7796-imr-lx4" for R-Car M3-W.
-- reg: offset and length of the register block;
-- interrupts: single interrupt specifier;
-- clocks: single clock phandle/specifier pair;
-- power-domains: power domain phandle/specifier pair;
-- resets: reset phandle/specifier pair.
-
-Example:
-
-       imr-lx4@fe860000 {
-               compatible = "renesas,r8a7795-imr-lx4", "renesas,imr-lx4";
-               reg = <0 0xfe860000 0 0x2000>;
-               interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&cpg CPG_MOD 823>;
-               power-domains = <&sysc R8A7795_PD_A3VC>;
-               resets = <&cpg 823>;
-       };
diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt
deleted file mode 100644 (file)
index aa217b0..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-Renesas R-Car Video Input driver (rcar_vin)
--------------------------------------------
-
-The rcar_vin device provides video input capabilities for the Renesas R-Car
-family of devices.
-
-Each VIN instance has a single parallel input that supports RGB and YUV video,
-with both external synchronization and BT.656 synchronization for the latter.
-Depending on the instance the VIN input is connected to external SoC pins, or
-on Gen3 and RZ/G2 platforms to a CSI-2 receiver.
-
- - compatible: Must be one or more of the following
-   - "renesas,vin-r8a7743" for the R8A7743 device
-   - "renesas,vin-r8a7744" for the R8A7744 device
-   - "renesas,vin-r8a7745" for the R8A7745 device
-   - "renesas,vin-r8a774a1" for the R8A774A1 device
-   - "renesas,vin-r8a774c0" for the R8A774C0 device
-   - "renesas,vin-r8a7778" for the R8A7778 device
-   - "renesas,vin-r8a7779" for the R8A7779 device
-   - "renesas,vin-r8a7790" for the R8A7790 device
-   - "renesas,vin-r8a7791" for the R8A7791 device
-   - "renesas,vin-r8a7792" for the R8A7792 device
-   - "renesas,vin-r8a7793" for the R8A7793 device
-   - "renesas,vin-r8a7794" for the R8A7794 device
-   - "renesas,vin-r8a7795" for the R8A7795 device
-   - "renesas,vin-r8a7796" for the R8A7796 device
-   - "renesas,vin-r8a77965" for the R8A77965 device
-   - "renesas,vin-r8a77970" for the R8A77970 device
-   - "renesas,vin-r8a77980" for the R8A77980 device
-   - "renesas,vin-r8a77990" for the R8A77990 device
-   - "renesas,vin-r8a77995" for the R8A77995 device
-   - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 or RZ/G1 compatible
-     device.
-
-   When compatible with the generic version nodes must list the
-   SoC-specific version corresponding to the platform first
-   followed by the generic version.
-
- - reg: the register base and size for the device registers
- - interrupts: the interrupt for the device
- - clocks: Reference to the parent clock
-
-Additionally, an alias named vinX will need to be created to specify
-which video input device this is.
-
-The per-board settings Gen2 platforms:
-
-- port - sub-node describing a single endpoint connected to the VIN
-  from external SoC pins as described in video-interfaces.txt[1].
-  Only the first one will be considered as each vin interface has one
-  input port.
-
-  - Optional properties for endpoint nodes:
-    - hsync-active: see [1] for description. Default is active high.
-    - vsync-active: see [1] for description. Default is active high.
-      If both HSYNC and VSYNC polarities are not specified, embedded
-      synchronization is selected.
-    - field-active-even: see [1] for description. Default is active high.
-    - bus-width: see [1] for description. The selected bus width depends on
-      the SoC type and selected input image format.
-      Valid values are: 8, 10, 12, 16, 24 and 32.
-    - data-shift: see [1] for description. Valid values are 0 and 8.
-    - data-enable-active: polarity of CLKENB signal, see [1] for
-      description. Default is active high.
-
-The per-board settings Gen3 and RZ/G2 platforms:
-
-Gen3 and RZ/G2 platforms can support both a single connected parallel input
-source from external SoC pins (port@0) and/or multiple parallel input sources
-from local SoC CSI-2 receivers (port@1) depending on SoC.
-
-- renesas,id - ID number of the VIN, VINx in the documentation.
-- ports
-    - port@0 - sub-node describing a single endpoint connected to the VIN
-      from external SoC pins as described in video-interfaces.txt[1].
-      Describing more than one endpoint in port@0 is invalid. Only VIN
-      instances that are connected to external pins should have port@0.
-
-      Endpoint nodes of port@0 support the optional properties listed in
-      the Gen2 per-board settings description.
-
-    - port@1 - sub-nodes describing one or more endpoints connected to
-      the VIN from local SoC CSI-2 receivers. The endpoint numbers must
-      use the following schema.
-
-        - endpoint@0 - sub-node describing the endpoint connected to CSI20
-        - endpoint@1 - sub-node describing the endpoint connected to CSI21
-        - endpoint@2 - sub-node describing the endpoint connected to CSI40
-        - endpoint@3 - sub-node describing the endpoint connected to CSI41
-
-      Endpoint nodes of port@1 do not support any optional endpoint property.
-
-Device node example for Gen2 platforms
---------------------------------------
-
-        aliases {
-                vin0 = &vin0;
-        };
-
-        vin0: vin@e6ef0000 {
-                compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin";
-                clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
-                reg = <0 0xe6ef0000 0 0x1000>;
-                interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>;
-                status = "disabled";
-        };
-
-Board setup example for Gen2 platforms (vin1 composite video input)
--------------------------------------------------------------------
-
-&i2c2   {
-        status = "okay";
-        pinctrl-0 = <&i2c2_pins>;
-        pinctrl-names = "default";
-
-        adv7180@20 {
-                compatible = "adi,adv7180";
-                reg = <0x20>;
-                remote = <&vin1>;
-
-                port {
-                        adv7180: endpoint {
-                                bus-width = <8>;
-                                remote-endpoint = <&vin1ep0>;
-                        };
-                };
-        };
-};
-
-/* composite video input */
-&vin1 {
-        pinctrl-0 = <&vin1_pins>;
-        pinctrl-names = "default";
-
-        status = "okay";
-
-        port {
-                vin1ep0: endpoint {
-                        remote-endpoint = <&adv7180>;
-                        bus-width = <8>;
-                };
-        };
-};
-
-Device node example for Gen3 platforms
---------------------------------------
-
-        vin0: video@e6ef0000 {
-                compatible = "renesas,vin-r8a7795";
-                reg = <0 0xe6ef0000 0 0x1000>;
-                interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-                clocks = <&cpg CPG_MOD 811>;
-                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
-                resets = <&cpg 811>;
-                renesas,id = <0>;
-
-                ports {
-                        #address-cells = <1>;
-                        #size-cells = <0>;
-
-                        port@1 {
-                                #address-cells = <1>;
-                                #size-cells = <0>;
-
-                                reg = <1>;
-
-                                vin0csi20: endpoint@0 {
-                                        reg = <0>;
-                                        remote-endpoint= <&csi20vin0>;
-                                };
-                                vin0csi21: endpoint@1 {
-                                        reg = <1>;
-                                        remote-endpoint= <&csi21vin0>;
-                                };
-                                vin0csi40: endpoint@2 {
-                                        reg = <2>;
-                                        remote-endpoint= <&csi40vin0>;
-                                };
-                        };
-                };
-        };
-
-        csi20: csi2@fea80000 {
-                compatible = "renesas,r8a7795-csi2";
-                reg = <0 0xfea80000 0 0x10000>;
-                interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
-                clocks = <&cpg CPG_MOD 714>;
-                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
-                resets = <&cpg 714>;
-
-                ports {
-                        #address-cells = <1>;
-                        #size-cells = <0>;
-
-                        port@0 {
-                                reg = <0>;
-                                csi20_in: endpoint {
-                                        clock-lanes = <0>;
-                                        data-lanes = <1>;
-                                        remote-endpoint = <&adv7482_txb>;
-                                };
-                        };
-
-                        port@1 {
-                                #address-cells = <1>;
-                                #size-cells = <0>;
-
-                                reg = <1>;
-
-                                csi20vin0: endpoint@0 {
-                                        reg = <0>;
-                                        remote-endpoint = <&vin0csi20>;
-                                };
-                        };
-                };
-        };
-
-[1] video-interfaces.txt common video media interface
diff --git a/Documentation/devicetree/bindings/media/renesas,csi2.txt b/Documentation/devicetree/bindings/media/renesas,csi2.txt
new file mode 100644 (file)
index 0000000..3314092
--- /dev/null
@@ -0,0 +1,106 @@
+Renesas R-Car MIPI CSI-2
+------------------------
+
+The R-Car CSI-2 receiver device provides MIPI CSI-2 capabilities for the
+Renesas R-Car and RZ/G2 family of devices. It is used in conjunction with the
+R-Car VIN module, which provides the video capture capabilities.
+
+Mandatory properties
+--------------------
+ - compatible: Must be one or more of the following
+   - "renesas,r8a774a1-csi2" for the R8A774A1 device.
+   - "renesas,r8a774c0-csi2" for the R8A774C0 device.
+   - "renesas,r8a7795-csi2" for the R8A7795 device.
+   - "renesas,r8a7796-csi2" for the R8A7796 device.
+   - "renesas,r8a77965-csi2" for the R8A77965 device.
+   - "renesas,r8a77970-csi2" for the R8A77970 device.
+   - "renesas,r8a77980-csi2" for the R8A77980 device.
+   - "renesas,r8a77990-csi2" for the R8A77990 device.
+
+ - reg: the register base and size for the device registers
+ - interrupts: the interrupt for the device
+ - clocks: A phandle + clock specifier for the module clock
+ - resets: A phandle + reset specifier for the module reset
+
+The device node shall contain two 'port' child nodes according to the
+bindings defined in Documentation/devicetree/bindings/media/
+video-interfaces.txt. port@0 shall connect to the CSI-2 source. port@1
+shall connect to all the R-Car VIN modules that have a hardware
+connection to the CSI-2 receiver.
+
+- port@0- Video source (mandatory)
+       - endpoint@0 - sub-node describing the endpoint that is the video source
+
+- port@1 - VIN instances (optional)
+       - One endpoint sub-node for every R-Car VIN instance which is connected
+         to the R-Car CSI-2 receiver.
+
+Example:
+
+       csi20: csi2@fea80000 {
+               compatible = "renesas,r8a7796-csi2";
+               reg = <0 0xfea80000 0 0x10000>;
+               interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cpg CPG_MOD 714>;
+               power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+               resets = <&cpg 714>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               reg = <0>;
+
+                               csi20_in: endpoint@0 {
+                                       reg = <0>;
+                                       clock-lanes = <0>;
+                                       data-lanes = <1>;
+                                       remote-endpoint = <&adv7482_txb>;
+                               };
+                       };
+
+                       port@1 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               reg = <1>;
+
+                               csi20vin0: endpoint@0 {
+                                       reg = <0>;
+                                       remote-endpoint = <&vin0csi20>;
+                               };
+                               csi20vin1: endpoint@1 {
+                                       reg = <1>;
+                                       remote-endpoint = <&vin1csi20>;
+                               };
+                               csi20vin2: endpoint@2 {
+                                       reg = <2>;
+                                       remote-endpoint = <&vin2csi20>;
+                               };
+                               csi20vin3: endpoint@3 {
+                                       reg = <3>;
+                                       remote-endpoint = <&vin3csi20>;
+                               };
+                               csi20vin4: endpoint@4 {
+                                       reg = <4>;
+                                       remote-endpoint = <&vin4csi20>;
+                               };
+                               csi20vin5: endpoint@5 {
+                                       reg = <5>;
+                                       remote-endpoint = <&vin5csi20>;
+                               };
+                               csi20vin6: endpoint@6 {
+                                       reg = <6>;
+                                       remote-endpoint = <&vin6csi20>;
+                               };
+                               csi20vin7: endpoint@7 {
+                                       reg = <7>;
+                                       remote-endpoint = <&vin7csi20>;
+                               };
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/media/renesas,imr.txt b/Documentation/devicetree/bindings/media/renesas,imr.txt
new file mode 100644 (file)
index 0000000..b061415
--- /dev/null
@@ -0,0 +1,31 @@
+Renesas R-Car Image Renderer (Distortion Correction Engine)
+-----------------------------------------------------------
+
+The image renderer, or the distortion correction engine, is a drawing processor
+with a simple instruction system capable of referencing video capture data or
+data in an external memory as 2D texture data and performing texture mapping
+and drawing with respect to any shape that is split into triangular objects.
+
+Required properties:
+
+- compatible: "renesas,<soctype>-imr-lx4", "renesas,imr-lx4" as a fallback for
+  the image renderer light extended 4 (IMR-LX4) found in the R-Car gen3 SoCs,
+  where the examples with <soctype> are:
+  - "renesas,r8a7795-imr-lx4" for R-Car H3,
+  - "renesas,r8a7796-imr-lx4" for R-Car M3-W.
+- reg: offset and length of the register block;
+- interrupts: single interrupt specifier;
+- clocks: single clock phandle/specifier pair;
+- power-domains: power domain phandle/specifier pair;
+- resets: reset phandle/specifier pair.
+
+Example:
+
+       imr-lx4@fe860000 {
+               compatible = "renesas,r8a7795-imr-lx4", "renesas,imr-lx4";
+               reg = <0 0xfe860000 0 0x2000>;
+               interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cpg CPG_MOD 823>;
+               power-domains = <&sysc R8A7795_PD_A3VC>;
+               resets = <&cpg 823>;
+       };
diff --git a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt b/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt
deleted file mode 100644 (file)
index 3314092..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-Renesas R-Car MIPI CSI-2
-------------------------
-
-The R-Car CSI-2 receiver device provides MIPI CSI-2 capabilities for the
-Renesas R-Car and RZ/G2 family of devices. It is used in conjunction with the
-R-Car VIN module, which provides the video capture capabilities.
-
-Mandatory properties
---------------------
- - compatible: Must be one or more of the following
-   - "renesas,r8a774a1-csi2" for the R8A774A1 device.
-   - "renesas,r8a774c0-csi2" for the R8A774C0 device.
-   - "renesas,r8a7795-csi2" for the R8A7795 device.
-   - "renesas,r8a7796-csi2" for the R8A7796 device.
-   - "renesas,r8a77965-csi2" for the R8A77965 device.
-   - "renesas,r8a77970-csi2" for the R8A77970 device.
-   - "renesas,r8a77980-csi2" for the R8A77980 device.
-   - "renesas,r8a77990-csi2" for the R8A77990 device.
-
- - reg: the register base and size for the device registers
- - interrupts: the interrupt for the device
- - clocks: A phandle + clock specifier for the module clock
- - resets: A phandle + reset specifier for the module reset
-
-The device node shall contain two 'port' child nodes according to the
-bindings defined in Documentation/devicetree/bindings/media/
-video-interfaces.txt. port@0 shall connect to the CSI-2 source. port@1
-shall connect to all the R-Car VIN modules that have a hardware
-connection to the CSI-2 receiver.
-
-- port@0- Video source (mandatory)
-       - endpoint@0 - sub-node describing the endpoint that is the video source
-
-- port@1 - VIN instances (optional)
-       - One endpoint sub-node for every R-Car VIN instance which is connected
-         to the R-Car CSI-2 receiver.
-
-Example:
-
-       csi20: csi2@fea80000 {
-               compatible = "renesas,r8a7796-csi2";
-               reg = <0 0xfea80000 0 0x10000>;
-               interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&cpg CPG_MOD 714>;
-               power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
-               resets = <&cpg 714>;
-
-               ports {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       port@0 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               reg = <0>;
-
-                               csi20_in: endpoint@0 {
-                                       reg = <0>;
-                                       clock-lanes = <0>;
-                                       data-lanes = <1>;
-                                       remote-endpoint = <&adv7482_txb>;
-                               };
-                       };
-
-                       port@1 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               reg = <1>;
-
-                               csi20vin0: endpoint@0 {
-                                       reg = <0>;
-                                       remote-endpoint = <&vin0csi20>;
-                               };
-                               csi20vin1: endpoint@1 {
-                                       reg = <1>;
-                                       remote-endpoint = <&vin1csi20>;
-                               };
-                               csi20vin2: endpoint@2 {
-                                       reg = <2>;
-                                       remote-endpoint = <&vin2csi20>;
-                               };
-                               csi20vin3: endpoint@3 {
-                                       reg = <3>;
-                                       remote-endpoint = <&vin3csi20>;
-                               };
-                               csi20vin4: endpoint@4 {
-                                       reg = <4>;
-                                       remote-endpoint = <&vin4csi20>;
-                               };
-                               csi20vin5: endpoint@5 {
-                                       reg = <5>;
-                                       remote-endpoint = <&vin5csi20>;
-                               };
-                               csi20vin6: endpoint@6 {
-                                       reg = <6>;
-                                       remote-endpoint = <&vin6csi20>;
-                               };
-                               csi20vin7: endpoint@7 {
-                                       reg = <7>;
-                                       remote-endpoint = <&vin7csi20>;
-                               };
-                       };
-               };
-       };
diff --git a/Documentation/devicetree/bindings/media/renesas,vin.txt b/Documentation/devicetree/bindings/media/renesas,vin.txt
new file mode 100644 (file)
index 0000000..aa217b0
--- /dev/null
@@ -0,0 +1,218 @@
+Renesas R-Car Video Input driver (rcar_vin)
+-------------------------------------------
+
+The rcar_vin device provides video input capabilities for the Renesas R-Car
+family of devices.
+
+Each VIN instance has a single parallel input that supports RGB and YUV video,
+with both external synchronization and BT.656 synchronization for the latter.
+Depending on the instance the VIN input is connected to external SoC pins, or
+on Gen3 and RZ/G2 platforms to a CSI-2 receiver.
+
+ - compatible: Must be one or more of the following
+   - "renesas,vin-r8a7743" for the R8A7743 device
+   - "renesas,vin-r8a7744" for the R8A7744 device
+   - "renesas,vin-r8a7745" for the R8A7745 device
+   - "renesas,vin-r8a774a1" for the R8A774A1 device
+   - "renesas,vin-r8a774c0" for the R8A774C0 device
+   - "renesas,vin-r8a7778" for the R8A7778 device
+   - "renesas,vin-r8a7779" for the R8A7779 device
+   - "renesas,vin-r8a7790" for the R8A7790 device
+   - "renesas,vin-r8a7791" for the R8A7791 device
+   - "renesas,vin-r8a7792" for the R8A7792 device
+   - "renesas,vin-r8a7793" for the R8A7793 device
+   - "renesas,vin-r8a7794" for the R8A7794 device
+   - "renesas,vin-r8a7795" for the R8A7795 device
+   - "renesas,vin-r8a7796" for the R8A7796 device
+   - "renesas,vin-r8a77965" for the R8A77965 device
+   - "renesas,vin-r8a77970" for the R8A77970 device
+   - "renesas,vin-r8a77980" for the R8A77980 device
+   - "renesas,vin-r8a77990" for the R8A77990 device
+   - "renesas,vin-r8a77995" for the R8A77995 device
+   - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 or RZ/G1 compatible
+     device.
+
+   When compatible with the generic version nodes must list the
+   SoC-specific version corresponding to the platform first
+   followed by the generic version.
+
+ - reg: the register base and size for the device registers
+ - interrupts: the interrupt for the device
+ - clocks: Reference to the parent clock
+
+Additionally, an alias named vinX will need to be created to specify
+which video input device this is.
+
+The per-board settings Gen2 platforms:
+
+- port - sub-node describing a single endpoint connected to the VIN
+  from external SoC pins as described in video-interfaces.txt[1].
+  Only the first one will be considered as each vin interface has one
+  input port.
+
+  - Optional properties for endpoint nodes:
+    - hsync-active: see [1] for description. Default is active high.
+    - vsync-active: see [1] for description. Default is active high.
+      If both HSYNC and VSYNC polarities are not specified, embedded
+      synchronization is selected.
+    - field-active-even: see [1] for description. Default is active high.
+    - bus-width: see [1] for description. The selected bus width depends on
+      the SoC type and selected input image format.
+      Valid values are: 8, 10, 12, 16, 24 and 32.
+    - data-shift: see [1] for description. Valid values are 0 and 8.
+    - data-enable-active: polarity of CLKENB signal, see [1] for
+      description. Default is active high.
+
+The per-board settings Gen3 and RZ/G2 platforms:
+
+Gen3 and RZ/G2 platforms can support both a single connected parallel input
+source from external SoC pins (port@0) and/or multiple parallel input sources
+from local SoC CSI-2 receivers (port@1) depending on SoC.
+
+- renesas,id - ID number of the VIN, VINx in the documentation.
+- ports
+    - port@0 - sub-node describing a single endpoint connected to the VIN
+      from external SoC pins as described in video-interfaces.txt[1].
+      Describing more than one endpoint in port@0 is invalid. Only VIN
+      instances that are connected to external pins should have port@0.
+
+      Endpoint nodes of port@0 support the optional properties listed in
+      the Gen2 per-board settings description.
+
+    - port@1 - sub-nodes describing one or more endpoints connected to
+      the VIN from local SoC CSI-2 receivers. The endpoint numbers must
+      use the following schema.
+
+        - endpoint@0 - sub-node describing the endpoint connected to CSI20
+        - endpoint@1 - sub-node describing the endpoint connected to CSI21
+        - endpoint@2 - sub-node describing the endpoint connected to CSI40
+        - endpoint@3 - sub-node describing the endpoint connected to CSI41
+
+      Endpoint nodes of port@1 do not support any optional endpoint property.
+
+Device node example for Gen2 platforms
+--------------------------------------
+
+        aliases {
+                vin0 = &vin0;
+        };
+
+        vin0: vin@e6ef0000 {
+                compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin";
+                clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
+                reg = <0 0xe6ef0000 0 0x1000>;
+                interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>;
+                status = "disabled";
+        };
+
+Board setup example for Gen2 platforms (vin1 composite video input)
+-------------------------------------------------------------------
+
+&i2c2   {
+        status = "okay";
+        pinctrl-0 = <&i2c2_pins>;
+        pinctrl-names = "default";
+
+        adv7180@20 {
+                compatible = "adi,adv7180";
+                reg = <0x20>;
+                remote = <&vin1>;
+
+                port {
+                        adv7180: endpoint {
+                                bus-width = <8>;
+                                remote-endpoint = <&vin1ep0>;
+                        };
+                };
+        };
+};
+
+/* composite video input */
+&vin1 {
+        pinctrl-0 = <&vin1_pins>;
+        pinctrl-names = "default";
+
+        status = "okay";
+
+        port {
+                vin1ep0: endpoint {
+                        remote-endpoint = <&adv7180>;
+                        bus-width = <8>;
+                };
+        };
+};
+
+Device node example for Gen3 platforms
+--------------------------------------
+
+        vin0: video@e6ef0000 {
+                compatible = "renesas,vin-r8a7795";
+                reg = <0 0xe6ef0000 0 0x1000>;
+                interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+                clocks = <&cpg CPG_MOD 811>;
+                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                resets = <&cpg 811>;
+                renesas,id = <0>;
+
+                ports {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        port@1 {
+                                #address-cells = <1>;
+                                #size-cells = <0>;
+
+                                reg = <1>;
+
+                                vin0csi20: endpoint@0 {
+                                        reg = <0>;
+                                        remote-endpoint= <&csi20vin0>;
+                                };
+                                vin0csi21: endpoint@1 {
+                                        reg = <1>;
+                                        remote-endpoint= <&csi21vin0>;
+                                };
+                                vin0csi40: endpoint@2 {
+                                        reg = <2>;
+                                        remote-endpoint= <&csi40vin0>;
+                                };
+                        };
+                };
+        };
+
+        csi20: csi2@fea80000 {
+                compatible = "renesas,r8a7795-csi2";
+                reg = <0 0xfea80000 0 0x10000>;
+                interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+                clocks = <&cpg CPG_MOD 714>;
+                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                resets = <&cpg 714>;
+
+                ports {
+                        #address-cells = <1>;
+                        #size-cells = <0>;
+
+                        port@0 {
+                                reg = <0>;
+                                csi20_in: endpoint {
+                                        clock-lanes = <0>;
+                                        data-lanes = <1>;
+                                        remote-endpoint = <&adv7482_txb>;
+                                };
+                        };
+
+                        port@1 {
+                                #address-cells = <1>;
+                                #size-cells = <0>;
+
+                                reg = <1>;
+
+                                csi20vin0: endpoint@0 {
+                                        reg = <0>;
+                                        remote-endpoint = <&vin0csi20>;
+                                };
+                        };
+                };
+        };
+
+[1] video-interfaces.txt common video media interface
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt b/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.txt
new file mode 100644 (file)
index 0000000..9f78e6c
--- /dev/null
@@ -0,0 +1,44 @@
+DT bindings for Renesas R-Mobile and SH-Mobile memory controllers
+=================================================================
+
+Renesas R-Mobile and SH-Mobile SoCs contain one or more memory controllers.
+These memory controllers differ from one SoC variant to another, and are called
+by different names ("DDR Bus Controller (DBSC)", "DDR3 Bus State Controller
+(DBSC3)", "SDRAM Bus State Controller (SBSC)").
+
+Currently memory controller device nodes are used only to reference PM
+domains, and prevent these PM domains from being powered down, which would
+crash the system.
+
+As there exist no actual drivers for these controllers yet, these bindings
+should be considered EXPERIMENTAL for now.
+
+Required properties:
+  - compatible: Must be one of the following SoC-specific values:
+                 - "renesas,dbsc-r8a73a4" (R-Mobile APE6)
+                 - "renesas,dbsc3-r8a7740" (R-Mobile A1)
+                 - "renesas,sbsc-sh73a0" (SH-Mobile AG5)
+  - reg: Must contain the base address and length of the memory controller's
+        registers.
+
+Optional properties:
+  - interrupts: Must contain a list of interrupt specifiers for memory
+               controller interrupts, if available.
+  - interrupt-names: Must contain a list of interrupt names corresponding to
+                    the interrupts in the interrupts property, if available.
+                    Valid interrupt names are:
+                       - "sec" (secure interrupt)
+                       - "temp" (normal (temperature) interrupt)
+  - power-domains: Must contain a reference to the PM domain that the memory
+                  controller belongs to, if available.
+
+Example:
+
+       sbsc1: memory-controller@fe400000 {
+               compatible = "renesas,sbsc-sh73a0";
+               reg = <0xfe400000 0x400>;
+               interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 36 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "sec", "temp";
+               power-domains = <&pd_a4bc0>;
+       };
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt b/Documentation/devicetree/bindings/memory-controllers/renesas-memory-controllers.txt
deleted file mode 100644 (file)
index 9f78e6c..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-DT bindings for Renesas R-Mobile and SH-Mobile memory controllers
-=================================================================
-
-Renesas R-Mobile and SH-Mobile SoCs contain one or more memory controllers.
-These memory controllers differ from one SoC variant to another, and are called
-by different names ("DDR Bus Controller (DBSC)", "DDR3 Bus State Controller
-(DBSC3)", "SDRAM Bus State Controller (SBSC)").
-
-Currently memory controller device nodes are used only to reference PM
-domains, and prevent these PM domains from being powered down, which would
-crash the system.
-
-As there exist no actual drivers for these controllers yet, these bindings
-should be considered EXPERIMENTAL for now.
-
-Required properties:
-  - compatible: Must be one of the following SoC-specific values:
-                 - "renesas,dbsc-r8a73a4" (R-Mobile APE6)
-                 - "renesas,dbsc3-r8a7740" (R-Mobile A1)
-                 - "renesas,sbsc-sh73a0" (SH-Mobile AG5)
-  - reg: Must contain the base address and length of the memory controller's
-        registers.
-
-Optional properties:
-  - interrupts: Must contain a list of interrupt specifiers for memory
-               controller interrupts, if available.
-  - interrupt-names: Must contain a list of interrupt names corresponding to
-                    the interrupts in the interrupts property, if available.
-                    Valid interrupt names are:
-                       - "sec" (secure interrupt)
-                       - "temp" (normal (temperature) interrupt)
-  - power-domains: Must contain a reference to the PM domain that the memory
-                  controller belongs to, if available.
-
-Example:
-
-       sbsc1: memory-controller@fe400000 {
-               compatible = "renesas,sbsc-sh73a0";
-               reg = <0xfe400000 0x400>;
-               interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 36 IRQ_TYPE_LEVEL_HIGH>;
-               interrupt-names = "sec", "temp";
-               power-domains = <&pd_a4bc0>;
-       };
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 (file)
index 0000000..4b1a09a
--- /dev/null
@@ -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 (file)
index 86dd819..0000000
+++ /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-ahb-queue-manager.yaml b/Documentation/devicetree/bindings/misc/intel,ixp4xx-ahb-queue-manager.yaml
new file mode 100644 (file)
index 0000000..0ea21a6
--- /dev/null
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 Linaro Ltd.
+%YAML 1.2
+---
+$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
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+  The IXP4xx AHB Queue Manager maintains queues as circular buffers in
+  an 8KB embedded SRAM along with hardware pointers. It is used by both
+  the XScale processor and the NPEs (Network Processing Units) in the
+  IXP4xx for accelerating queues, especially for networking. Clients pick
+  queues from the queue manager with foo-queue = <&qmgr N> where the
+  &qmgr is a phandle to the queue manager and N is the queue resource
+  number. The queue resources available and their specific purpose
+  on a certain IXP4xx system will vary.
+
+properties:
+  compatible:
+    items:
+      - const: intel,ixp4xx-ahb-queue-manager
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    items:
+      - description: Interrupt for queues 0-31
+      - description: Interrupt for queues 32-63
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    qmgr: queue-manager@60000000 {
+         compatible = "intel,ixp4xx-ahb-queue-manager";
+         reg = <0x60000000 0x4000>;
+         interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>;
+    };
diff --git a/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml b/Documentation/devicetree/bindings/misc/intel,ixp4xx-queue-manager.yaml
deleted file mode 100644 (file)
index d2313b1..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-# Copyright 2019 Linaro Ltd.
-%YAML 1.2
----
-$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
-
-maintainers:
-  - Linus Walleij <linus.walleij@linaro.org>
-
-description: |
-  The IXP4xx AHB Queue Manager maintains queues as circular buffers in
-  an 8KB embedded SRAM along with hardware pointers. It is used by both
-  the XScale processor and the NPEs (Network Processing Units) in the
-  IXP4xx for accelerating queues, especially for networking. Clients pick
-  queues from the queue manager with foo-queue = <&qmgr N> where the
-  &qmgr is a phandle to the queue manager and N is the queue resource
-  number. The queue resources available and their specific purpose
-  on a certain IXP4xx system will vary.
-
-properties:
-  compatible:
-    items:
-      - const: intel,ixp4xx-ahb-queue-manager
-
-  reg:
-    maxItems: 1
-
-  interrupts:
-    items:
-      - description: Interrupt for queues 0-31
-      - description: Interrupt for queues 32-63
-
-required:
-  - compatible
-  - reg
-  - interrupts
-
-examples:
-  - |
-    #include <dt-bindings/interrupt-controller/irq.h>
-
-    qmgr: queue-manager@60000000 {
-         compatible = "intel,ixp4xx-ahb-queue-manager";
-         reg = <0x60000000 0x4000>;
-         interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>;
-    };
index d4084c1..3fb0714 100644 (file)
@@ -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
index b463e12..19e4a7d 100644 (file)
@@ -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
index 32f051f..a901cd9 100644 (file)
@@ -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.
index c9efd6e..1084e9d 100644 (file)
@@ -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 (file)
index 0000000..b7c00ed
--- /dev/null
@@ -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";
+    };
index fd06c09..46a7ef4 100644 (file)
@@ -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 (file)
index 0000000..1c75a05
--- /dev/null
@@ -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>;
+          };
+      };
+
+...
index 250f9d5..fa46670 100644 (file)
@@ -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/riscv/cpus.txt b/Documentation/devicetree/bindings/riscv/cpus.txt
deleted file mode 100644 (file)
index adf7b7a..0000000
+++ /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";
-                        }
-                }
-        }
index c899111..b261a30 100644 (file)
@@ -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
index 9d17dc2..3ab5327 100644 (file)
@@ -19,7 +19,7 @@ properties:
   compatible:
     items:
       - enum:
-          - sifive,freedom-unleashed-a00
+          - sifive,hifive-unleashed-a00
       - const: sifive,fu540-c000
       - const: sifive,fu540
 ...
index 21483ba..3495eee 100644 (file)
@@ -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.
index 6fdffb7..3a3b570 100644 (file)
@@ -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
index 876c062..a02e2fe 100644 (file)
@@ -73,7 +73,6 @@ patternProperties:
           Compatible of the SPI device.
 
       reg:
-        maxItems: 1
         minimum: 0
         maximum: 256
         description:
index dcc7eaa..162e024 100644 (file)
@@ -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.
index a36a074..2807225 100644 (file)
@@ -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
index bc7945e..17915f6 100644 (file)
@@ -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 {
index 85965e3..e60b58d 100644 (file)
@@ -83,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,.*":
@@ -271,6 +273,8 @@ patternProperties:
     description: Emerging Display Technologies
   "^eeti,.*":
     description: eGalax_eMPIA Technology Inc
+  "^einfochips,.*":
+    description: Einfochips
   "^elan,.*":
     description: Elan Microelectronic Corp.
   "^elgin,.*":
@@ -505,6 +509,8 @@ patternProperties:
     description: Lantiq Semiconductor
   "^lattice,.*":
     description: Lattice Semiconductor
+  "^leez,.*":
+    description: Leez
   "^lego,.*":
     description: LEGO Systems A/S
   "^lemaker,.*":
@@ -551,6 +557,8 @@ patternProperties:
     description: mCube
   "^meas,.*":
     description: Measurement Specialties
+  "^mecer,.*":
+    description: Mustek Limited
   "^mediatek,.*":
     description: MediaTek Inc.
   "^megachips,.*":
diff --git a/Documentation/doc-guide/conf.py b/Documentation/doc-guide/conf.py
deleted file mode 100644 (file)
index fd37311..0000000
+++ /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 (file)
index 4424b4b..0000000
+++ /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 (file)
index 202726d..0000000
+++ /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'),
-]
index 0c161b1..8382f01 100644 (file)
@@ -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
index 457c3e0..8fc1ce0 100644 (file)
@@ -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 (file)
index a89fac1..0000000
+++ /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'),
-]
index 9267f3f..edbbccd 100644 (file)
@@ -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 (file)
index ea44172..0000000
+++ /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 (file)
index 1757b04..0000000
+++ /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'),
-]
index 72da12a..fe91095 100644 (file)
@@ -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
 
index 70ae148..2df5a3d 100644 (file)
@@ -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 (file)
index d2352fd..0000000
+++ /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 (file)
index 3d8acf0..0000000
+++ /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'),
-]
index 098107f..e93ec66 100644 (file)
@@ -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 (file)
index 81e9eb7..0000000
+++ /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 (file)
index 1f194fc..0000000
+++ /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'),
-]
index 045bb81..1adbb8a 100644 (file)
@@ -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 (file)
index 40f69e6..0000000
+++ /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'),
-]
index 048e5ca..b70b70d 100644 (file)
@@ -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
 ============================================================
index 20415f2..002e427 100644 (file)
@@ -1,4 +1,4 @@
-:orphan:
+.. SPDX-License-Identifier: GPL-2.0
 
 ================
 Power Management
diff --git a/Documentation/powerpc/DAWR-POWER9.txt b/Documentation/powerpc/DAWR-POWER9.txt
deleted file mode 100644 (file)
index ecdbb07..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-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:
-
-    commit 9654153158d3e0684a1bdb76dbababdb7111d5a0
-    Author: Michael Neuling <mikey@neuling.org>
-    Date:   Tue Mar 27 15:37:24 2018 +1100
-    powerpc: Disable DAWR in the base POWER9 CPU features
-
-Technical Details:
-============================
-
-DAWR has 6 different ways of being set.
-1) ptrace
-2) h_set_mode(DAWR)
-3) h_set_dabr()
-4) kvmppc_set_one_reg()
-5) xmon
-
-For ptrace, we now advertise zero breakpoints on POWER9 via the
-PPC_PTRACE_GETHWDBGINFO call. This results in GDB falling back to
-software emulation of the watchpoint (which is slow).
-
-h_set_mode(DAWR) and h_set_dabr() will now return an error to the
-guest on a POWER9 host. Current Linux guests ignore this error, so
-they will silently not get the DAWR.
-
-kvmppc_set_one_reg() will store the value in the vcpu but won't
-actually set it on POWER9 hardware. This is done so we don't break
-migration from POWER8 to POWER9, at the cost of silently losing the
-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
-support for the watchpoint, GDB will software emulate the watchpoint
-making it run very slowly.
-
-The same will also be true for any guests started on a POWER9
-host. The watchpoint will fail and GDB will fall back to software
-emulation.
-
-If a guest is started on a POWER8 host, GDB will accept the watchpoint
-and configure the hardware to use the DAWR. This will run at full
-speed since it can use the hardware emulation. Unfortunately if this
-guest is migrated to a POWER9 host, the watchpoint will be lost on the
-POWER9. Loads and stores to the watchpoint locations will not be
-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:
-
-  echo Y > /sys/kernel/debug/powerpc/dawr_enable_dangerous
-
-This enables the DAWR even on POWER9.
-
-This is a dangerous setting, USE AT YOUR OWN RISK.
-
-Some users may not care about a bad user crashing their box
-(ie. single user/desktop systems) and really want the DAWR.  This
-allows them to force enable DAWR.
-
-This flag can also be used to disable DAWR access. Once this is
-cleared, all DAWR access should be cleared immediately and your
-machine once again safe from crashing.
-
-Userspace may get confused by toggling this. If DAWR is force
-enabled/disabled between getting the number of breakpoints (via
-PTRACE_GETHWDBGINFO) and setting the breakpoint, userspace will get an
-inconsistent view of what's available. Similarly for guests.
-
-For the DAWR to be enabled in a KVM guest, the DAWR needs to be force
-enabled in the host AND the guest. For this reason, this won't work on
-POWERVM as it doesn't allow the HCALL to work. Writes of 'Y' to the
-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/bootwrapper.rst b/Documentation/powerpc/bootwrapper.rst
new file mode 100644 (file)
index 0000000..a6292af
--- /dev/null
@@ -0,0 +1,155 @@
+========================
+The PowerPC boot wrapper
+========================
+
+Copyright (C) Secret Lab Technologies Ltd.
+
+PowerPC image targets compresses and wraps the kernel image (vmlinux) with
+a boot wrapper to make it usable by the system firmware.  There is no
+standard PowerPC firmware interface, so the boot wrapper is designed to
+be adaptable for each kind of image that needs to be built.
+
+The boot wrapper can be found in the arch/powerpc/boot/ directory.  The
+Makefile in that directory has targets for all the available image types.
+The different image types are used to support all of the various firmware
+interfaces found on PowerPC platforms.  OpenFirmware is the most commonly
+used firmware type on general purpose PowerPC systems from Apple, IBM and
+others.  U-Boot is typically found on embedded PowerPC hardware, but there
+are a handful of other firmware implementations which are also popular.  Each
+firmware interface requires a different image format.
+
+The boot wrapper is built from the makefile in arch/powerpc/boot/Makefile and
+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
+                       the image.  The boot wrapper, kernel and device tree
+                       are all embedded inside the U-Boot uImage file format
+                       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
+                       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
+                       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
+                       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
+                       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
+                       can be loaded to any location in RAM and jumped to.
+                       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
+                       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
+                       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
+                       is enabled.  Platform specific initialization code is
+                       added as part of the wrapper script and is keyed on
+                       the image target name.  For example, all
+                       simpleImage.virtex405-* targets will add the
+                       virtex405-head.S initialization code (This also means
+                       that the dts file for virtex405 targets should be
+                       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
+                       requires a version of U-Boot that is able to pass
+                       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
+arch/powerpc/boot/dts/ directory.  The Makefile selects the correct device
+tree source based on the name of the target.  Therefore, if the kernel is
+built with 'make treeImage.walnut simpleImage.virtex405-ml403', then the
+build system will use arch/powerpc/boot/dts/walnut.dts to build
+treeImage.walnut and arch/powerpc/boot/dts/virtex405-ml403.dts to build
+the simpleImage.virtex405-ml403.
+
+Two special targets called 'zImage' and 'zImage.initrd' also exist.  These
+targets build all the default images as selected by the kernel configuration.
+Default images are selected by the boot wrapper Makefile
+(arch/powerpc/boot/Makefile) by adding targets to the $image-y variable.  Look
+at the Makefile to see which default image targets are available.
+
+How it is built
+---------------
+arch/powerpc is designed to support multiplatform kernels, which means
+that a single vmlinux image can be booted on many different target boards.
+It also means that the boot wrapper must be able to wrap for many kinds of
+images on a single build.  The design decision was made to not use any
+conditional compilation code (#ifdef, etc) in the boot wrapper source code.
+All of the boot wrapper pieces are buildable at any time regardless of the
+kernel configuration.  Building all the wrapper bits on every kernel build
+also ensures that obscure parts of the wrapper are at the very least compile
+tested in a large variety of environments.
+
+The wrapper is adapted for different image types at link time by linking in
+just the wrapper bits that are appropriate for the image type.  The 'wrapper
+script' (found in arch/powerpc/boot/wrapper) is called by the Makefile and
+is responsible for selecting the correct wrapper bits for the image type.
+The arguments are well documented in the script's comment block, so they
+are not repeated here.  However, it is worth mentioning that the script
+uses the -p (platform) argument as the main method of deciding which wrapper
+bits to compile in.  Look for the large 'case "$platform" in' block in the
+middle of the script.  This is also the place where platform specific fixups
+can be selected by changing the link order.
+
+In particular, care should be taken when working with cuImages.  cuImage
+wrapper bits are very board specific and care should be taken to make sure
+the target you are trying to build is supported by the wrapper bits.
diff --git a/Documentation/powerpc/bootwrapper.txt b/Documentation/powerpc/bootwrapper.txt
deleted file mode 100644 (file)
index d60fced..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-The PowerPC boot wrapper
-------------------------
-Copyright (C) Secret Lab Technologies Ltd.
-
-PowerPC image targets compresses and wraps the kernel image (vmlinux) with
-a boot wrapper to make it usable by the system firmware.  There is no
-standard PowerPC firmware interface, so the boot wrapper is designed to
-be adaptable for each kind of image that needs to be built.
-
-The boot wrapper can be found in the arch/powerpc/boot/ directory.  The
-Makefile in that directory has targets for all the available image types.
-The different image types are used to support all of the various firmware
-interfaces found on PowerPC platforms.  OpenFirmware is the most commonly
-used firmware type on general purpose PowerPC systems from Apple, IBM and
-others.  U-Boot is typically found on embedded PowerPC hardware, but there
-are a handful of other firmware implementations which are also popular.  Each
-firmware interface requires a different image format.
-
-The boot wrapper is built from the makefile in arch/powerpc/boot/Makefile and
-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
-                       the image.  The boot wrapper, kernel and device tree
-                       are all embedded inside the U-Boot uImage file format
-                       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
-                       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
-                       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
-                       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
-                       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
-                       can be loaded to any location in RAM and jumped to.
-                       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
-                       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
-                       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
-                       is enabled.  Platform specific initialization code is
-                       added as part of the wrapper script and is keyed on
-                       the image target name.  For example, all
-                       simpleImage.virtex405-* targets will add the
-                       virtex405-head.S initialization code (This also means
-                       that the dts file for virtex405 targets should be
-                       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
-                       requires a version of U-Boot that is able to pass
-                       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
-arch/powerpc/boot/dts/ directory.  The Makefile selects the correct device
-tree source based on the name of the target.  Therefore, if the kernel is
-built with 'make treeImage.walnut simpleImage.virtex405-ml403', then the
-build system will use arch/powerpc/boot/dts/walnut.dts to build
-treeImage.walnut and arch/powerpc/boot/dts/virtex405-ml403.dts to build
-the simpleImage.virtex405-ml403.
-
-Two special targets called 'zImage' and 'zImage.initrd' also exist.  These
-targets build all the default images as selected by the kernel configuration.
-Default images are selected by the boot wrapper Makefile
-(arch/powerpc/boot/Makefile) by adding targets to the $image-y variable.  Look
-at the Makefile to see which default image targets are available.
-
-How it is built
----------------
-arch/powerpc is designed to support multiplatform kernels, which means
-that a single vmlinux image can be booted on many different target boards.
-It also means that the boot wrapper must be able to wrap for many kinds of
-images on a single build.  The design decision was made to not use any
-conditional compilation code (#ifdef, etc) in the boot wrapper source code.
-All of the boot wrapper pieces are buildable at any time regardless of the
-kernel configuration.  Building all the wrapper bits on every kernel build
-also ensures that obscure parts of the wrapper are at the very least compile
-tested in a large variety of environments.
-
-The wrapper is adapted for different image types at link time by linking in
-just the wrapper bits that are appropriate for the image type.  The 'wrapper
-script' (found in arch/powerpc/boot/wrapper) is called by the Makefile and
-is responsible for selecting the correct wrapper bits for the image type.
-The arguments are well documented in the script's comment block, so they
-are not repeated here.  However, it is worth mentioning that the script
-uses the -p (platform) argument as the main method of deciding which wrapper
-bits to compile in.  Look for the large 'case "$platform" in' block in the
-middle of the script.  This is also the place where platform specific fixups
-can be selected by changing the link order.
-
-In particular, care should be taken when working with cuImages.  cuImage
-wrapper bits are very board specific and care should be taken to make sure
-the target you are trying to build is supported by the wrapper bits.
diff --git a/Documentation/powerpc/cpu_families.rst b/Documentation/powerpc/cpu_families.rst
new file mode 100644 (file)
index 0000000..1e063c5
--- /dev/null
@@ -0,0 +1,222 @@
+============
+CPU Families
+============
+
+This document tries to summarise some of the different cpu families that exist
+and are supported by arch/powerpc.
+
+
+Book3S (aka sPAPR)
+------------------
+
+- Hash MMU
+- Mix of 32 & 64 bit::
+
+   +--------------+                 +----------------+
+   |  Old POWER   | --------------> | RS64 (threads) |
+   +--------------+                 +----------------+
+          |
+          |
+          v
+   +--------------+                 +----------------+      +------+
+   |     601      | --------------> |      603       | ---> | e300 |
+   +--------------+                 +----------------+      +------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+                 +----------------+      +-------+
+   |     604      |                 |    750 (G3)    | ---> | 750CX |
+   +--------------+                 +----------------+      +-------+
+          |                                 |                   |
+          |                                 |                   |
+          v                                 v                   v
+   +--------------+                 +----------------+      +-------+
+   | 620 (64 bit) |                 |      7400      |      | 750CL |
+   +--------------+                 +----------------+      +-------+
+          |                                 |                   |
+          |                                 |                   |
+          v                                 v                   v
+   +--------------+                 +----------------+      +-------+
+   |  POWER3/630  |                 |      7410      |      | 750FX |
+   +--------------+                 +----------------+      +-------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+                 +----------------+
+   |   POWER3+    |                 |      7450      |
+   +--------------+                 +----------------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+                 +----------------+
+   |    POWER4    |                 |      7455      |
+   +--------------+                 +----------------+
+          |                                 |
+          |                                 |
+          v                                 v
+   +--------------+     +-------+   +----------------+
+   |   POWER4+    | --> |  970  |   |      7447      |
+   +--------------+     +-------+   +----------------+
+          |                 |               |
+          |                 |               |
+          v                 v               v
+   +--------------+     +-------+   +----------------+
+   |    POWER5    |     | 970FX |   |      7448      |
+   +--------------+     +-------+   +----------------+
+          |                 |               |
+          |                 |               |
+          v                 v               v
+   +--------------+     +-------+   +----------------+
+   |   POWER5+    |     | 970MP |   |      e600      |
+   +--------------+     +-------+   +----------------+
+          |
+          |
+          v
+   +--------------+
+   |   POWER5++   |
+   +--------------+
+          |
+          |
+          v
+   +--------------+       +-------+
+   |    POWER6    | <-?-> | Cell  |
+   +--------------+       +-------+
+          |
+          |
+          v
+   +--------------+
+   |    POWER7    |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |   POWER7+    |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |    POWER8    |
+   +--------------+
+
+
+   +---------------+
+   | PA6T (64 bit) |
+   +---------------+
+
+
+IBM BookE
+---------
+
+- Software loaded TLB.
+- All 32 bit::
+
+   +--------------+
+   |     401      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     403      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     405      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     440      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+     +----------------+
+   |     450      | --> |      BG/P      |
+   +--------------+     +----------------+
+          |
+          |
+          v
+   +--------------+
+   |     460      |
+   +--------------+
+          |
+          |
+          v
+   +--------------+
+   |     476      |
+   +--------------+
+
+
+Motorola/Freescale 8xx
+----------------------
+
+- Software loaded with hardware assist.
+- All 32 bit::
+
+   +-------------+
+   | MPC8xx Core |
+   +-------------+
+
+
+Freescale BookE
+---------------
+
+- Software loaded TLB.
+- e6500 adds HW loaded indirect TLB entries.
+- Mix of 32 & 64 bit::
+
+   +--------------+
+   |     e200     |
+   +--------------+
+
+
+   +--------------------------------+
+   |              e500              |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   |             e500v2             |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   |        e500mc (Book3e)         |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   |          e5500 (64 bit)        |
+   +--------------------------------+
+                   |
+                   |
+                   v
+   +--------------------------------+
+   | e6500 (HW TLB) (Multithreaded) |
+   +--------------------------------+
+
+
+IBM A2 core
+-----------
+
+- Book3E, software loaded TLB + HW loaded indirect TLB entries.
+- 64 bit::
+
+   +--------------+     +----------------+
+   |   A2 core    | --> |      WSP       |
+   +--------------+     +----------------+
+           |
+           |
+           v
+   +--------------+
+   |     BG/Q     |
+   +--------------+
diff --git a/Documentation/powerpc/cpu_families.txt b/Documentation/powerpc/cpu_families.txt
deleted file mode 100644 (file)
index fc08e22..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-CPU Families
-============
-
-This document tries to summarise some of the different cpu families that exist
-and are supported by arch/powerpc.
-
-
-Book3S (aka sPAPR)
-------------------
-
- - Hash MMU
- - Mix of 32 & 64 bit
-
-   +--------------+                 +----------------+
-   |  Old POWER   | --------------> | RS64 (threads) |
-   +--------------+                 +----------------+
-          |
-          |
-          v
-   +--------------+                 +----------------+      +------+
-   |     601      | --------------> |      603       | ---> | e300 |
-   +--------------+                 +----------------+      +------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+                 +----------------+      +-------+
-   |     604      |                 |    750 (G3)    | ---> | 750CX |
-   +--------------+                 +----------------+      +-------+
-          |                                 |                   |
-          |                                 |                   |
-          v                                 v                   v
-   +--------------+                 +----------------+      +-------+
-   | 620 (64 bit) |                 |      7400      |      | 750CL |
-   +--------------+                 +----------------+      +-------+
-          |                                 |                   |
-          |                                 |                   |
-          v                                 v                   v
-   +--------------+                 +----------------+      +-------+
-   |  POWER3/630  |                 |      7410      |      | 750FX |
-   +--------------+                 +----------------+      +-------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+                 +----------------+
-   |   POWER3+    |                 |      7450      |
-   +--------------+                 +----------------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+                 +----------------+
-   |    POWER4    |                 |      7455      |
-   +--------------+                 +----------------+
-          |                                 |
-          |                                 |
-          v                                 v
-   +--------------+     +-------+   +----------------+
-   |   POWER4+    | --> |  970  |   |      7447      |
-   +--------------+     +-------+   +----------------+
-          |                 |               |
-          |                 |               |
-          v                 v               v
-   +--------------+     +-------+   +----------------+
-   |    POWER5    |     | 970FX |   |      7448      |
-   +--------------+     +-------+   +----------------+
-          |                 |               |
-          |                 |               |
-          v                 v               v
-   +--------------+     +-------+   +----------------+
-   |   POWER5+    |     | 970MP |   |      e600      |
-   +--------------+     +-------+   +----------------+
-          |
-          |
-          v
-   +--------------+
-   |   POWER5++   |
-   +--------------+
-          |
-          |
-          v
-   +--------------+       +-------+
-   |    POWER6    | <-?-> | Cell  |
-   +--------------+       +-------+
-          |
-          |
-          v
-   +--------------+
-   |    POWER7    |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |   POWER7+    |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |    POWER8    |
-   +--------------+
-
-
-   +---------------+
-   | PA6T (64 bit) |
-   +---------------+
-
-
-IBM BookE
----------
-
- - Software loaded TLB.
- - All 32 bit
-
-   +--------------+
-   |     401      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     403      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     405      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     440      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+     +----------------+
-   |     450      | --> |      BG/P      |
-   +--------------+     +----------------+
-          |
-          |
-          v
-   +--------------+
-   |     460      |
-   +--------------+
-          |
-          |
-          v
-   +--------------+
-   |     476      |
-   +--------------+
-
-
-Motorola/Freescale 8xx
-----------------------
-
- - Software loaded with hardware assist.
- - All 32 bit
-
-   +-------------+
-   | MPC8xx Core |
-   +-------------+
-
-
-Freescale BookE
----------------
-
- - Software loaded TLB.
- - e6500 adds HW loaded indirect TLB entries.
- - Mix of 32 & 64 bit
-
-   +--------------+
-   |     e200     |
-   +--------------+
-
-
-   +--------------------------------+
-   |              e500              |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   |             e500v2             |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   |        e500mc (Book3e)         |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   |          e5500 (64 bit)        |
-   +--------------------------------+
-                   |
-                   |
-                   v
-   +--------------------------------+
-   | e6500 (HW TLB) (Multithreaded) |
-   +--------------------------------+
-
-
-IBM A2 core
------------
-
- - Book3E, software loaded TLB + HW loaded indirect TLB entries.
- - 64 bit
-
-   +--------------+     +----------------+
-   |   A2 core    | --> |      WSP       |
-   +--------------+     +----------------+
-           |
-           |
-           v
-   +--------------+
-   |     BG/Q     |
-   +--------------+
diff --git a/Documentation/powerpc/cpu_features.rst b/Documentation/powerpc/cpu_features.rst
new file mode 100644 (file)
index 0000000..b7bcdd2
--- /dev/null
@@ -0,0 +1,60 @@
+============
+CPU Features
+============
+
+Hollis Blanchard <hollis@austin.ibm.com>
+5 Jun 2002
+
+This document describes the system (including self-modifying code) used in the
+PPC Linux kernel to support a variety of PowerPC CPUs without requiring
+compile-time selection.
+
+Early in the boot process the ppc32 kernel detects the current CPU type and
+chooses a set of features accordingly. Some examples include Altivec support,
+split instruction and data caches, and if the CPU supports the DOZE and NAP
+sleep modes.
+
+Detection of the feature set is simple. A list of processors can be found in
+arch/powerpc/kernel/cputable.c. The PVR register is masked and compared with
+each value in the list. If a match is found, the cpu_features of cur_cpu_spec
+is assigned to the feature bitmask for this processor and a __setup_cpu
+function is called.
+
+C code may test 'cur_cpu_spec[smp_processor_id()]->cpu_features' for a
+particular feature bit. This is done in quite a few places, for example
+in ppc_setup_l2cr().
+
+Implementing cpufeatures in assembly is a little more involved. There are
+several paths that are performance-critical and would suffer if an array
+index, structure dereference, and conditional branch were added. To avoid the
+performance penalty but still allow for runtime (rather than compile-time) CPU
+selection, unused code is replaced by 'nop' instructions. This nop'ing is
+based on CPU 0's capabilities, so a multi-processor system with non-identical
+processors will not work (but such a system would likely have other problems
+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::
+
+       #ifdef CONFIG_ALTIVEC
+       BEGIN_FTR_SECTION
+               mfspr   r22,SPRN_VRSAVE         /* if G4, save vrsave register value */
+               stw     r22,THREAD_VRSAVE(r23)
+       END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+       #endif /* CONFIG_ALTIVEC */
+
+If CPU 0 supports Altivec, the code is left untouched. If it doesn't, both
+instructions are replaced with nop's.
+
+The END_FTR_SECTION macro has two simpler variations: END_FTR_SECTION_IFSET
+and END_FTR_SECTION_IFCLR. These simply test if a flag is set (in
+cur_cpu_spec[0]->cpu_features) or is cleared, respectively. These two macros
+should be used in the majority of cases.
+
+The END_FTR_SECTION macros are implemented by storing information about this
+code in the '__ftr_fixup' ELF section. When do_cpu_ftr_fixups
+(arch/powerpc/kernel/misc.S) is invoked, it will iterate over the records in
+__ftr_fixup, and if the required feature is not present it will loop writing
+nop's from each BEGIN_FTR_SECTION to END_FTR_SECTION.
diff --git a/Documentation/powerpc/cpu_features.txt b/Documentation/powerpc/cpu_features.txt
deleted file mode 100644 (file)
index ae09df8..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-Hollis Blanchard <hollis@austin.ibm.com>
-5 Jun 2002
-
-This document describes the system (including self-modifying code) used in the
-PPC Linux kernel to support a variety of PowerPC CPUs without requiring
-compile-time selection.
-
-Early in the boot process the ppc32 kernel detects the current CPU type and
-chooses a set of features accordingly. Some examples include Altivec support,
-split instruction and data caches, and if the CPU supports the DOZE and NAP
-sleep modes.
-
-Detection of the feature set is simple. A list of processors can be found in
-arch/powerpc/kernel/cputable.c. The PVR register is masked and compared with
-each value in the list. If a match is found, the cpu_features of cur_cpu_spec
-is assigned to the feature bitmask for this processor and a __setup_cpu
-function is called.
-
-C code may test 'cur_cpu_spec[smp_processor_id()]->cpu_features' for a
-particular feature bit. This is done in quite a few places, for example
-in ppc_setup_l2cr().
-
-Implementing cpufeatures in assembly is a little more involved. There are
-several paths that are performance-critical and would suffer if an array
-index, structure dereference, and conditional branch were added. To avoid the
-performance penalty but still allow for runtime (rather than compile-time) CPU
-selection, unused code is replaced by 'nop' instructions. This nop'ing is
-based on CPU 0's capabilities, so a multi-processor system with non-identical
-processors will not work (but such a system would likely have other problems
-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:
-
-       #ifdef CONFIG_ALTIVEC
-       BEGIN_FTR_SECTION
-               mfspr   r22,SPRN_VRSAVE         /* if G4, save vrsave register value */
-               stw     r22,THREAD_VRSAVE(r23)
-       END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-       #endif /* CONFIG_ALTIVEC */
-
-If CPU 0 supports Altivec, the code is left untouched. If it doesn't, both
-instructions are replaced with nop's.
-
-The END_FTR_SECTION macro has two simpler variations: END_FTR_SECTION_IFSET
-and END_FTR_SECTION_IFCLR. These simply test if a flag is set (in
-cur_cpu_spec[0]->cpu_features) or is cleared, respectively. These two macros
-should be used in the majority of cases.
-
-The END_FTR_SECTION macros are implemented by storing information about this
-code in the '__ftr_fixup' ELF section. When do_cpu_ftr_fixups
-(arch/powerpc/kernel/misc.S) is invoked, it will iterate over the records in
-__ftr_fixup, and if the required feature is not present it will loop writing
-nop's from each BEGIN_FTR_SECTION to END_FTR_SECTION.
diff --git a/Documentation/powerpc/cxl.rst b/Documentation/powerpc/cxl.rst
new file mode 100644 (file)
index 0000000..920546d
--- /dev/null
@@ -0,0 +1,467 @@
+====================================
+Coherent Accelerator Interface (CXL)
+====================================
+
+Introduction
+============
+
+    The coherent accelerator interface is designed to allow the
+    coherent connection of accelerators (FPGAs and other devices) to a
+    POWER system. These devices need to adhere to the Coherent
+    Accelerator Interface Architecture (CAIA).
+
+    IBM refers to this as the Coherent Accelerator Processor Interface
+    or CAPI. In the kernel it's referred to by the name CXL to avoid
+    confusion with the ISDN CAPI subsystem.
+
+    Coherent in this context means that the accelerator and CPUs can
+    both access system memory directly and with the same effective
+    addresses.
+
+
+Hardware overview
+=================
+
+    ::
+
+         POWER8/9             FPGA
+       +----------+        +---------+
+       |          |        |         |
+       |   CPU    |        |   AFU   |
+       |          |        |         |
+       |          |        |         |
+       |          |        |         |
+       +----------+        +---------+
+       |   PHB    |        |         |
+       |   +------+        |   PSL   |
+       |   | CAPP |<------>|         |
+       +---+------+  PCIE  +---------+
+
+    The POWER8/9 chip has a Coherently Attached Processor Proxy (CAPP)
+    unit which is part of the PCIe Host Bridge (PHB). This is managed
+    by Linux by calls into OPAL. Linux doesn't directly program the
+    CAPP.
+
+    The FPGA (or coherently attached device) consists of two parts.
+    The POWER Service Layer (PSL) and the Accelerator Function Unit
+    (AFU). The AFU is used to implement specific functionality behind
+    the PSL. The PSL, among other things, provides memory address
+    translation services to allow each AFU direct access to userspace
+    memory.
+
+    The AFU is the core part of the accelerator (eg. the compression,
+    crypto etc function). The kernel has no knowledge of the function
+    of the AFU. Only userspace interacts directly with the AFU.
+
+    The PSL provides the translation and interrupt services that the
+    AFU needs. This is what the kernel interacts with. For example, if
+    the AFU needs to read a particular effective address, it sends
+    that address to the PSL, the PSL then translates it, fetches the
+    data from memory and returns it to the AFU. If the PSL has a
+    translation miss, it interrupts the kernel and the kernel services
+    the fault. The context to which this fault is serviced is based on
+    who owns that acceleration function.
+
+    - 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.
+
+AFU Modes
+=========
+
+    There are two programming modes supported by the AFU. Dedicated
+    and AFU directed. AFU may support one or both modes.
+
+    When using dedicated mode only one MMU context is supported. In
+    this mode, only one userspace process can use the accelerator at
+    time.
+
+    When using AFU directed mode, up to 16K simultaneous contexts can
+    be supported. This means up to 16K simultaneous userspace
+    applications may use the accelerator (although specific AFUs may
+    support fewer). In this mode, the AFU sends a 16 bit context ID
+    with each of its requests. This tells the PSL which context is
+    associated with each operation. If the PSL can't translate an
+    operation, the ID can also be accessed by the kernel so it can
+    determine the userspace context associated with an operation.
+
+
+MMIO space
+==========
+
+    A portion of the accelerator MMIO space can be directly mapped
+    from the AFU to userspace. Either the whole space can be mapped or
+    just a per context portion. The hardware is self describing, hence
+    the kernel can determine the offset and size of the per context
+    portion.
+
+
+Interrupts
+==========
+
+    AFUs may generate interrupts that are destined for userspace. These
+    are received by the kernel as hardware interrupts and passed onto
+    userspace by a read syscall documented below.
+
+    Data storage faults and error interrupts are handled by the kernel
+    driver.
+
+
+Work Element Descriptor (WED)
+=============================
+
+    The WED is a 64-bit parameter passed to the AFU when a context is
+    started. Its format is up to the AFU hence the kernel has no
+    knowledge of what it represents. Typically it will be the
+    effective address of a work queue or status block where the AFU
+    and userspace can share control and status information.
+
+
+
+
+User API
+========
+
+1. AFU character devices
+
+    For AFUs operating in AFU directed mode, two character device
+    files will be created. /dev/cxl/afu0.0m will correspond to a
+    master context and /dev/cxl/afu0.0s will correspond to a slave
+    context. Master contexts have access to the full MMIO space an
+    AFU provides. Slave contexts have access to only the per process
+    MMIO space an AFU provides.
+
+    For AFUs operating in dedicated process mode, the driver will
+    only create a single character device per AFU called
+    /dev/cxl/afu0.0d. This will have access to the entire MMIO space
+    that the AFU provides (like master contexts in AFU directed).
+
+    The types described below are defined in include/uapi/misc/cxl.h
+
+    The following file operations are supported on both slave and
+    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
+----
+
+    Opens the device and allocates a file descriptor to be used with
+    the rest of the API.
+
+    A dedicated mode AFU only has one context and only allows the
+    device to be opened once.
+
+    An AFU directed mode AFU can have many contexts, the device can be
+    opened once for each context that is available.
+
+    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
+          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
+          left. If 1 IRQ is needed per context, then only 2037
+          contexts can be allocated. If 4 IRQs are needed per context,
+          then only 2037/4 = 509 contexts can be allocated.
+
+
+ioctl
+-----
+
+    CXL_IOCTL_START_WORK:
+        Starts the AFU context and associates it with the current
+        process. Once this ioctl is successfully executed, all memory
+        mapped into this process is accessible to this AFU context
+        using the same effective addresses. No additional calls are
+        required to map/unmap memory. The AFU memory context will be
+        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
+
+            ::
+
+                struct cxl_ioctl_start_work {
+                        __u64 flags;
+                        __u64 work_element_descriptor;
+                        __u64 amr;
+                        __s16 num_interrupts;
+                        __s16 reserved1;
+                        __s32 reserved2;
+                        __u64 reserved3;
+                        __u64 reserved4;
+                        __u64 reserved5;
+                        __u64 reserved6;
+                };
+
+            flags:
+                Indicates which optional fields in the structure are
+                valid.
+
+            work_element_descriptor:
+                The Work Element Descriptor (WED) is a 64-bit argument
+                defined by the AFU. Typically this is an effective
+                address pointing to an AFU specific structure
+                describing what work to perform.
+
+            amr:
+                Authority Mask Register (AMR), same as the powerpc
+                AMR. This field is only used by the kernel when the
+                corresponding CXL_START_WORK_AMR value is specified in
+                flags. If not specified the kernel will use a default
+                value of 0.
+
+            num_interrupts:
+                Number of userspace interrupts to request. This field
+                is only used by the kernel when the corresponding
+                CXL_START_WORK_NUM_IRQS value is specified in flags.
+                If not specified the minimum number required by the
+                AFU will be allocated. The min and max number can be
+                obtained from sysfs.
+
+            reserved fields:
+                For ABI padding and future extensions
+
+    CXL_IOCTL_GET_PROCESS_ELEMENT:
+        Get the current context id, also known as the process element.
+        The value is returned from the kernel as a __u32.
+
+
+mmap
+----
+
+    An AFU may have an MMIO space to facilitate communication with the
+    AFU. If it does, the MMIO space can be accessed via mmap. The size
+    and contents of this area are specific to the particular AFU. The
+    size can be discovered via sysfs.
+
+    In AFU directed mode, master contexts are allowed to map all of
+    the MMIO space and slave contexts are allowed to only map the per
+    process MMIO space associated with the context. In dedicated
+    process mode the entire MMIO space can always be mapped.
+
+    This mmap call must be done after the START_WORK ioctl.
+
+    Care should be taken when accessing MMIO space. Only 32 and 64-bit
+    accesses are supported by POWER8. Also, the AFU will be designed
+    with a specific endianness, so all MMIO accesses should consider
+    endianness (recommend endian(3) variants like: le64toh(),
+    be64toh() etc). These endian issues equally apply to shared memory
+    queues the WED may describe.
+
+
+read
+----
+
+    Reads events from the AFU. Blocks if no events are pending
+    (unless O_NONBLOCK is supplied). Returns -EIO in the case of an
+    unrecoverable error or if the card is removed.
+
+    read() will always return an integral number of events.
+
+    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::
+
+            struct cxl_event {
+                    struct cxl_event_header header;
+                    union {
+                            struct cxl_event_afu_interrupt irq;
+                            struct cxl_event_data_storage fault;
+                            struct cxl_event_afu_error afu_error;
+                    };
+            };
+
+    The struct cxl_event_header is defined as
+
+        ::
+
+            struct cxl_event_header {
+                    __u16 type;
+                    __u16 size;
+                    __u16 process_element;
+                    __u16 reserved1;
+            };
+
+        type:
+            This defines the type of event. The type determines how
+            the rest of the event is structured. These types are
+            described below and defined by enum cxl_event_type.
+
+        size:
+            This is the size of the event in bytes including the
+            struct cxl_event_header. The start of the next event can
+            be found at this offset from the start of the current
+            event.
+
+        process_element:
+            Context ID of the event.
+
+        reserved field:
+            For future extensions and padding.
+
+    If the event type is CXL_EVENT_AFU_INTERRUPT then the event
+    structure is defined as
+
+        ::
+
+            struct cxl_event_afu_interrupt {
+                    __u16 flags;
+                    __u16 irq; /* Raised AFU interrupt number */
+                    __u32 reserved1;
+            };
+
+        flags:
+            These flags indicate which optional fields are present
+            in this struct. Currently all fields are mandatory.
+
+        irq:
+            The IRQ number sent by the AFU.
+
+        reserved field:
+            For future extensions and padding.
+
+    If the event type is CXL_EVENT_DATA_STORAGE then the event
+    structure is defined as
+
+        ::
+
+            struct cxl_event_data_storage {
+                    __u16 flags;
+                    __u16 reserved1;
+                    __u32 reserved2;
+                    __u64 addr;
+                    __u64 dsisr;
+                    __u64 reserved3;
+            };
+
+        flags:
+            These flags indicate which optional fields are present in
+            this struct. Currently all fields are mandatory.
+
+        address:
+            The address that the AFU unsuccessfully attempted to
+            access. Valid accesses will be handled transparently by the
+            kernel but invalid accesses will generate this event.
+
+        dsisr:
+            This field gives information on the type of fault. It is a
+            copy of the DSISR from the PSL hardware when the address
+            fault occurred. The form of the DSISR is as defined in the
+            CAIA.
+
+        reserved fields:
+            For future extensions
+
+    If the event type is CXL_EVENT_AFU_ERROR then the event structure
+    is defined as
+
+        ::
+
+            struct cxl_event_afu_error {
+                    __u16 flags;
+                    __u16 reserved1;
+                    __u32 reserved2;
+                    __u64 error;
+            };
+
+        flags:
+            These flags indicate which optional fields are present in
+            this struct. Currently all fields are Mandatory.
+
+        error:
+            Error status from the AFU. Defined by the AFU.
+
+        reserved fields:
+            For future extensions and padding
+
+
+2. Card character device (powerVM guest only)
+
+    In a powerVM guest, an extra character device is created for the
+    card. The device is only used to write (flash) a new image on the
+    FPGA accelerator. Once the image is written and verified, the
+    device tree is updated and the card is reset to reload the updated
+    image.
+
+open
+----
+
+    Opens the device and allocates a file descriptor to be used with
+    the rest of the API. The device can only be opened once.
+
+ioctl
+-----
+
+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::
+
+        struct cxl_adapter_image {
+            __u64 flags;
+            __u64 data;
+            __u64 len_data;
+            __u64 len_image;
+            __u64 reserved1;
+            __u64 reserved2;
+            __u64 reserved3;
+            __u64 reserved4;
+        };
+
+    flags:
+        These flags indicate which optional fields are present in
+        this struct. Currently all fields are mandatory.
+
+    data:
+        Pointer to a buffer with part of the image to write to the
+        card.
+
+    len_data:
+        Size of the buffer pointed to by data.
+
+    len_image:
+        Full size of the image.
+
+
+Sysfs Class
+===========
+
+    A cxl sysfs class is added under /sys/class/cxl to facilitate
+    enumeration and tuning of the accelerators. Its layout is
+    described in Documentation/ABI/testing/sysfs-class-cxl
+
+
+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::
+
+       SUBSYSTEM=="cxl", ATTRS{mode}=="dedicated_process", SYMLINK="cxl/%b"
+       SUBSYSTEM=="cxl", ATTRS{mode}=="afu_directed", \
+                         KERNEL=="afu[0-9]*.[0-9]*s", SYMLINK="cxl/%b"
diff --git a/Documentation/powerpc/cxl.txt b/Documentation/powerpc/cxl.txt
deleted file mode 100644 (file)
index c5e8d50..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-Coherent Accelerator Interface (CXL)
-====================================
-
-Introduction
-============
-
-    The coherent accelerator interface is designed to allow the
-    coherent connection of accelerators (FPGAs and other devices) to a
-    POWER system. These devices need to adhere to the Coherent
-    Accelerator Interface Architecture (CAIA).
-
-    IBM refers to this as the Coherent Accelerator Processor Interface
-    or CAPI. In the kernel it's referred to by the name CXL to avoid
-    confusion with the ISDN CAPI subsystem.
-
-    Coherent in this context means that the accelerator and CPUs can
-    both access system memory directly and with the same effective
-    addresses.
-
-
-Hardware overview
-=================
-
-         POWER8/9             FPGA
-       +----------+        +---------+
-       |          |        |         |
-       |   CPU    |        |   AFU   |
-       |          |        |         |
-       |          |        |         |
-       |          |        |         |
-       +----------+        +---------+
-       |   PHB    |        |         |
-       |   +------+        |   PSL   |
-       |   | CAPP |<------>|         |
-       +---+------+  PCIE  +---------+
-
-    The POWER8/9 chip has a Coherently Attached Processor Proxy (CAPP)
-    unit which is part of the PCIe Host Bridge (PHB). This is managed
-    by Linux by calls into OPAL. Linux doesn't directly program the
-    CAPP.
-
-    The FPGA (or coherently attached device) consists of two parts.
-    The POWER Service Layer (PSL) and the Accelerator Function Unit
-    (AFU). The AFU is used to implement specific functionality behind
-    the PSL. The PSL, among other things, provides memory address
-    translation services to allow each AFU direct access to userspace
-    memory.
-
-    The AFU is the core part of the accelerator (eg. the compression,
-    crypto etc function). The kernel has no knowledge of the function
-    of the AFU. Only userspace interacts directly with the AFU.
-
-    The PSL provides the translation and interrupt services that the
-    AFU needs. This is what the kernel interacts with. For example, if
-    the AFU needs to read a particular effective address, it sends
-    that address to the PSL, the PSL then translates it, fetches the
-    data from memory and returns it to the AFU. If the PSL has a
-    translation miss, it interrupts the kernel and the kernel services
-    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.
-    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.
-    * ....
-
-    Cards with a PSL9 won't work on a POWER8 system and cards with a
-    PSL8 won't work on a POWER9 system.
-
-AFU Modes
-=========
-
-    There are two programming modes supported by the AFU. Dedicated
-    and AFU directed. AFU may support one or both modes.
-
-    When using dedicated mode only one MMU context is supported. In
-    this mode, only one userspace process can use the accelerator at
-    time.
-
-    When using AFU directed mode, up to 16K simultaneous contexts can
-    be supported. This means up to 16K simultaneous userspace
-    applications may use the accelerator (although specific AFUs may
-    support fewer). In this mode, the AFU sends a 16 bit context ID
-    with each of its requests. This tells the PSL which context is
-    associated with each operation. If the PSL can't translate an
-    operation, the ID can also be accessed by the kernel so it can
-    determine the userspace context associated with an operation.
-
-
-MMIO space
-==========
-
-    A portion of the accelerator MMIO space can be directly mapped
-    from the AFU to userspace. Either the whole space can be mapped or
-    just a per context portion. The hardware is self describing, hence
-    the kernel can determine the offset and size of the per context
-    portion.
-
-
-Interrupts
-==========
-
-    AFUs may generate interrupts that are destined for userspace. These
-    are received by the kernel as hardware interrupts and passed onto
-    userspace by a read syscall documented below.
-
-    Data storage faults and error interrupts are handled by the kernel
-    driver.
-
-
-Work Element Descriptor (WED)
-=============================
-
-    The WED is a 64-bit parameter passed to the AFU when a context is
-    started. Its format is up to the AFU hence the kernel has no
-    knowledge of what it represents. Typically it will be the
-    effective address of a work queue or status block where the AFU
-    and userspace can share control and status information.
-
-
-
-
-User API
-========
-
-1. AFU character devices
-
-    For AFUs operating in AFU directed mode, two character device
-    files will be created. /dev/cxl/afu0.0m will correspond to a
-    master context and /dev/cxl/afu0.0s will correspond to a slave
-    context. Master contexts have access to the full MMIO space an
-    AFU provides. Slave contexts have access to only the per process
-    MMIO space an AFU provides.
-
-    For AFUs operating in dedicated process mode, the driver will
-    only create a single character device per AFU called
-    /dev/cxl/afu0.0d. This will have access to the entire MMIO space
-    that the AFU provides (like master contexts in AFU directed).
-
-    The types described below are defined in include/uapi/misc/cxl.h
-
-    The following file operations are supported on both slave and
-    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
-----
-
-    Opens the device and allocates a file descriptor to be used with
-    the rest of the API.
-
-    A dedicated mode AFU only has one context and only allows the
-    device to be opened once.
-
-    An AFU directed mode AFU can have many contexts, the device can be
-    opened once for each context that is available.
-
-    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
-          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
-          left. If 1 IRQ is needed per context, then only 2037
-          contexts can be allocated. If 4 IRQs are needed per context,
-          then only 2037/4 = 509 contexts can be allocated.
-
-
-ioctl
------
-
-    CXL_IOCTL_START_WORK:
-        Starts the AFU context and associates it with the current
-        process. Once this ioctl is successfully executed, all memory
-        mapped into this process is accessible to this AFU context
-        using the same effective addresses. No additional calls are
-        required to map/unmap memory. The AFU memory context will be
-        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:
-
-                struct cxl_ioctl_start_work {
-                        __u64 flags;
-                        __u64 work_element_descriptor;
-                        __u64 amr;
-                        __s16 num_interrupts;
-                        __s16 reserved1;
-                        __s32 reserved2;
-                        __u64 reserved3;
-                        __u64 reserved4;
-                        __u64 reserved5;
-                        __u64 reserved6;
-                };
-
-            flags:
-                Indicates which optional fields in the structure are
-                valid.
-
-            work_element_descriptor:
-                The Work Element Descriptor (WED) is a 64-bit argument
-                defined by the AFU. Typically this is an effective
-                address pointing to an AFU specific structure
-                describing what work to perform.
-
-            amr:
-                Authority Mask Register (AMR), same as the powerpc
-                AMR. This field is only used by the kernel when the
-                corresponding CXL_START_WORK_AMR value is specified in
-                flags. If not specified the kernel will use a default
-                value of 0.
-
-            num_interrupts:
-                Number of userspace interrupts to request. This field
-                is only used by the kernel when the corresponding
-                CXL_START_WORK_NUM_IRQS value is specified in flags.
-                If not specified the minimum number required by the
-                AFU will be allocated. The min and max number can be
-                obtained from sysfs.
-
-            reserved fields:
-                For ABI padding and future extensions
-
-    CXL_IOCTL_GET_PROCESS_ELEMENT:
-        Get the current context id, also known as the process element.
-        The value is returned from the kernel as a __u32.
-
-
-mmap
-----
-
-    An AFU may have an MMIO space to facilitate communication with the
-    AFU. If it does, the MMIO space can be accessed via mmap. The size
-    and contents of this area are specific to the particular AFU. The
-    size can be discovered via sysfs.
-
-    In AFU directed mode, master contexts are allowed to map all of
-    the MMIO space and slave contexts are allowed to only map the per
-    process MMIO space associated with the context. In dedicated
-    process mode the entire MMIO space can always be mapped.
-
-    This mmap call must be done after the START_WORK ioctl.
-
-    Care should be taken when accessing MMIO space. Only 32 and 64-bit
-    accesses are supported by POWER8. Also, the AFU will be designed
-    with a specific endianness, so all MMIO accesses should consider
-    endianness (recommend endian(3) variants like: le64toh(),
-    be64toh() etc). These endian issues equally apply to shared memory
-    queues the WED may describe.
-
-
-read
-----
-
-    Reads events from the AFU. Blocks if no events are pending
-    (unless O_NONBLOCK is supplied). Returns -EIO in the case of an
-    unrecoverable error or if the card is removed.
-
-    read() will always return an integral number of events.
-
-    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.
-
-            struct cxl_event {
-                    struct cxl_event_header header;
-                    union {
-                            struct cxl_event_afu_interrupt irq;
-                            struct cxl_event_data_storage fault;
-                            struct cxl_event_afu_error afu_error;
-                    };
-            };
-
-    The struct cxl_event_header is defined as:
-
-            struct cxl_event_header {
-                    __u16 type;
-                    __u16 size;
-                    __u16 process_element;
-                    __u16 reserved1;
-            };
-
-        type:
-            This defines the type of event. The type determines how
-            the rest of the event is structured. These types are
-            described below and defined by enum cxl_event_type.
-
-        size:
-            This is the size of the event in bytes including the
-            struct cxl_event_header. The start of the next event can
-            be found at this offset from the start of the current
-            event.
-
-        process_element:
-            Context ID of the event.
-
-        reserved field:
-            For future extensions and padding.
-
-    If the event type is CXL_EVENT_AFU_INTERRUPT then the event
-    structure is defined as:
-
-            struct cxl_event_afu_interrupt {
-                    __u16 flags;
-                    __u16 irq; /* Raised AFU interrupt number */
-                    __u32 reserved1;
-            };
-
-        flags:
-            These flags indicate which optional fields are present
-            in this struct. Currently all fields are mandatory.
-
-        irq:
-            The IRQ number sent by the AFU.
-
-        reserved field:
-            For future extensions and padding.
-
-    If the event type is CXL_EVENT_DATA_STORAGE then the event
-    structure is defined as:
-
-            struct cxl_event_data_storage {
-                    __u16 flags;
-                    __u16 reserved1;
-                    __u32 reserved2;
-                    __u64 addr;
-                    __u64 dsisr;
-                    __u64 reserved3;
-            };
-
-        flags:
-            These flags indicate which optional fields are present in
-            this struct. Currently all fields are mandatory.
-
-        address:
-            The address that the AFU unsuccessfully attempted to
-            access. Valid accesses will be handled transparently by the
-            kernel but invalid accesses will generate this event.
-
-        dsisr:
-            This field gives information on the type of fault. It is a
-            copy of the DSISR from the PSL hardware when the address
-            fault occurred. The form of the DSISR is as defined in the
-            CAIA.
-
-        reserved fields:
-            For future extensions
-
-    If the event type is CXL_EVENT_AFU_ERROR then the event structure
-    is defined as:
-
-            struct cxl_event_afu_error {
-                    __u16 flags;
-                    __u16 reserved1;
-                    __u32 reserved2;
-                    __u64 error;
-            };
-
-        flags:
-            These flags indicate which optional fields are present in
-            this struct. Currently all fields are Mandatory.
-
-        error:
-            Error status from the AFU. Defined by the AFU.
-
-        reserved fields:
-            For future extensions and padding
-
-
-2. Card character device (powerVM guest only)
-
-    In a powerVM guest, an extra character device is created for the
-    card. The device is only used to write (flash) a new image on the
-    FPGA accelerator. Once the image is written and verified, the
-    device tree is updated and the card is reset to reload the updated
-    image.
-
-open
-----
-
-    Opens the device and allocates a file descriptor to be used with
-    the rest of the API. The device can only be opened once.
-
-ioctl
------
-
-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:
-        struct cxl_adapter_image {
-            __u64 flags;
-            __u64 data;
-            __u64 len_data;
-            __u64 len_image;
-            __u64 reserved1;
-            __u64 reserved2;
-            __u64 reserved3;
-            __u64 reserved4;
-        };
-
-    flags:
-        These flags indicate which optional fields are present in
-        this struct. Currently all fields are mandatory.
-
-    data:
-        Pointer to a buffer with part of the image to write to the
-        card.
-
-    len_data:
-        Size of the buffer pointed to by data.
-
-    len_image:
-        Full size of the image.
-
-
-Sysfs Class
-===========
-
-    A cxl sysfs class is added under /sys/class/cxl to facilitate
-    enumeration and tuning of the accelerators. Its layout is
-    described in Documentation/ABI/testing/sysfs-class-cxl
-
-
-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:
-
-       SUBSYSTEM=="cxl", ATTRS{mode}=="dedicated_process", SYMLINK="cxl/%b"
-       SUBSYSTEM=="cxl", ATTRS{mode}=="afu_directed", \
-                         KERNEL=="afu[0-9]*.[0-9]*s", SYMLINK="cxl/%b"
diff --git a/Documentation/powerpc/cxlflash.rst b/Documentation/powerpc/cxlflash.rst
new file mode 100644 (file)
index 0000000..cea6793
--- /dev/null
@@ -0,0 +1,433 @@
+================================
+Coherent Accelerator (CXL) Flash
+================================
+
+Introduction
+============
+
+    The IBM Power architecture provides support for CAPI (Coherent
+    Accelerator Power Interface), which is available to certain PCIe slots
+    on Power 8 systems. CAPI can be thought of as a special tunneling
+    protocol through PCIe that allow PCIe adapters to look like special
+    purpose co-processors which can read or write an application's
+    memory and generate page faults. As a result, the host interface to
+    an adapter running in CAPI mode does not require the data buffers to
+    be mapped to the device's memory (IOMMU bypass) nor does it require
+    memory to be pinned.
+
+    On Linux, Coherent Accelerator (CXL) kernel services present CAPI
+    devices as a PCI device by implementing a virtual PCI host bridge.
+    This abstraction simplifies the infrastructure and programming
+    model, allowing for drivers to look similar to other native PCI
+    device drivers.
+
+    CXL provides a mechanism by which user space applications can
+    directly talk to a device (network or storage) bypassing the typical
+    kernel/device driver stack. The CXL Flash Adapter Driver enables a
+    user space application direct access to Flash storage.
+
+    The CXL Flash Adapter Driver is a kernel module that sits in the
+    SCSI stack as a low level device driver (below the SCSI disk and
+    protocol drivers) for the IBM CXL Flash Adapter. This driver is
+    responsible for the initialization of the adapter, setting up the
+    special path for user space access, and performing error recovery. It
+    communicates directly the Flash Accelerator Functional Unit (AFU)
+    as described in Documentation/powerpc/cxl.rst.
+
+    The cxlflash driver supports two, mutually exclusive, modes of
+    operation at the device (LUN) level:
+
+        - Any flash device (LUN) can be configured to be accessed as a
+          regular disk device (i.e.: /dev/sdc). This is the default mode.
+
+        - Any flash device (LUN) can be configured to be accessed from
+          user space with a special block library. This mode further
+          specifies the means of accessing the device and provides for
+          either raw access to the entire LUN (referred to as direct
+          or physical LUN access) or access to a kernel/AFU-mediated
+          partition of the LUN (referred to as virtual LUN access). The
+          segmentation of a disk device into virtual LUNs is assisted
+          by special translation services provided by the Flash AFU.
+
+Overview
+========
+
+    The Coherent Accelerator Interface Architecture (CAIA) introduces a
+    concept of a master context. A master typically has special privileges
+    granted to it by the kernel or hypervisor allowing it to perform AFU
+    wide management and control. The master may or may not be involved
+    directly in each user I/O, but at the minimum is involved in the
+    initial setup before the user application is allowed to send requests
+    directly to the AFU.
+
+    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::
+
+                     +-------------------------------+
+                     |    512 * 64 KB User MMIO      |
+                     |        (per context)          |
+                     |       User Accessible         |
+                     +-------------------------------+
+                     |    512 * 128 B per context    |
+                     |    Provisioning and Control   |
+                     |   Trusted Process accessible  |
+                     +-------------------------------+
+                     |         64 KB Global          |
+                     |   Trusted Process accessible  |
+                     +-------------------------------+
+
+    This driver configures itself into the SCSI software stack as an
+    adapter driver. The driver is the only entity that is considered a
+    Trusted Process to program the Provisioning and Control and Global
+    areas in the MMIO Space shown above.  The master context driver
+    discovers all LUNs attached to the CXL Flash adapter and instantiates
+    scsi block devices (/dev/sdb, /dev/sdc etc.) for each unique LUN
+    seen from each path.
+
+    Once these scsi block devices are instantiated, an application
+    written to a specification provided by the block library may get
+    access to the Flash from user space (without requiring a system call).
+
+    This master context driver also provides a series of ioctls for this
+    block library to enable this user space access.  The driver supports
+    two modes for accessing the block device.
+
+    The first mode is called a virtual mode. In this mode a single scsi
+    block device (/dev/sdb) may be carved up into any number of distinct
+    virtual LUNs. The virtual LUNs may be resized as long as the sum of
+    the sizes of all the virtual LUNs, along with the meta-data associated
+    with it does not exceed the physical capacity.
+
+    The second mode is called the physical mode. In this mode a single
+    block device (/dev/sdb) may be opened directly by the block library
+    and the entire space for the LUN is available to the application.
+
+    Only the physical mode provides persistence of the data.  i.e. The
+    data written to the block device will survive application exit and
+    restart and also reboot. The virtual LUNs do not persist (i.e. do
+    not survive after the application terminates or the system reboots).
+
+
+Block library API
+=================
+
+    Applications intending to get access to the CXL Flash from user
+    space should use the block library, as it abstracts the details of
+    interfacing directly with the cxlflash driver that are necessary for
+    performing administrative actions (i.e.: setup, tear down, resize).
+    The block library can be thought of as a 'user' of services,
+    implemented as IOCTLs, that are provided by the cxlflash driver
+    specifically for devices (LUNs) operating in user space access
+    mode. While it is not a requirement that applications understand
+    the interface between the block library and the cxlflash driver,
+    a high-level overview of each supported service (IOCTL) is provided
+    below.
+
+    The block library can be found on GitHub:
+    http://github.com/open-power/capiflash
+
+
+CXL Flash Driver LUN IOCTLs
+===========================
+
+    Users, such as the block library, that wish to interface with a flash
+    device (LUN) via user space access need to use the services provided
+    by the cxlflash driver. As these services are implemented as ioctls,
+    a file descriptor handle must first be obtained in order to establish
+    the communication channel between a user and the kernel.  This file
+    descriptor is obtained by opening the device special file associated
+    with the scsi disk device (/dev/sdb) that was created during LUN
+    discovery. As per the location of the cxlflash driver within the
+    SCSI protocol stack, this open is actually not seen by the cxlflash
+    driver. Upon successful open, the user receives a file descriptor
+    (herein referred to as fd1) that should be used for issuing the
+    subsequent ioctls listed below.
+
+    The structure definitions for these IOCTLs are available in:
+    uapi/scsi/cxlflash_ioctl.h
+
+DK_CXLFLASH_ATTACH
+------------------
+
+    This ioctl obtains, initializes, and starts a context using the CXL
+    kernel services. These services specify a context id (u16) by which
+    to uniquely identify the context and its allocated resources. The
+    services additionally provide a second file descriptor (herein
+    referred to as fd2) that is used by the block library to initiate
+    memory mapped I/O (via mmap()) to the CXL flash device and poll for
+    completion events. This file descriptor is intentionally installed by
+    this driver and not the CXL kernel services to allow for intermediary
+    notification and access in the event of a non-user-initiated close(),
+    such as a killed process. This design point is described in further
+    detail in the description for the DK_CXLFLASH_DETACH ioctl.
+
+    There are a few important aspects regarding the "tokens" (context id
+    and fd2) that are provided back to the user:
+
+        - These tokens are only valid for the process under which they
+          were created. The child of a forked process cannot continue
+          to use the context id or file descriptor created by its parent
+          (see DK_CXLFLASH_VLUN_CLONE for further details).
+
+        - These tokens are only valid for the lifetime of the context and
+          the process under which they were created. Once either is
+          destroyed, the tokens are to be considered stale and subsequent
+          usage will result in errors.
+
+       - A valid adapter file descriptor (fd2 >= 0) is only returned on
+         the initial attach for a context. Subsequent attaches to an
+         existing context (DK_CXLFLASH_ATTACH_REUSE_CONTEXT flag present)
+         do not provide the adapter file descriptor as it was previously
+         made known to the application.
+
+        - When a context is no longer needed, the user shall detach from
+          the context via the DK_CXLFLASH_DETACH ioctl. When this ioctl
+         returns with a valid adapter file descriptor and the return flag
+         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
+         close the adapter file descriptor following a successful detach.
+
+       - When this ioctl returns with a valid fd2 and the return flag
+         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
+         close fd2 in the following circumstances:
+
+               + Following a successful detach of the last user of the context
+               + Following a successful recovery on the context's original fd2
+               + In the child process of a fork(), following a clone ioctl,
+                 on the fd2 associated with the source context
+
+        - At any time, a close on fd2 will invalidate the tokens. Applications
+         should exercise caution to only close fd2 when appropriate (outlined
+         in the previous bullet) to avoid premature loss of I/O.
+
+DK_CXLFLASH_USER_DIRECT
+-----------------------
+    This ioctl is responsible for transitioning the LUN to direct
+    (physical) mode access and configuring the AFU for direct access from
+    user space on a per-context basis. Additionally, the block size and
+    last logical block address (LBA) are returned to the user.
+
+    As mentioned previously, when operating in user space access mode,
+    LUNs may be accessed in whole or in part. Only one mode is allowed
+    at a time and if one mode is active (outstanding references exist),
+    requests to use the LUN in a different mode are denied.
+
+    The AFU is configured for direct access from user space by adding an
+    entry to the AFU's resource handle table. The index of the entry is
+    treated as a resource handle that is returned to the user. The user
+    is then able to use the handle to reference the LUN during I/O.
+
+DK_CXLFLASH_USER_VIRTUAL
+------------------------
+    This ioctl is responsible for transitioning the LUN to virtual mode
+    of access and configuring the AFU for virtual access from user space
+    on a per-context basis. Additionally, the block size and last logical
+    block address (LBA) are returned to the user.
+
+    As mentioned previously, when operating in user space access mode,
+    LUNs may be accessed in whole or in part. Only one mode is allowed
+    at a time and if one mode is active (outstanding references exist),
+    requests to use the LUN in a different mode are denied.
+
+    The AFU is configured for virtual access from user space by adding
+    an entry to the AFU's resource handle table. The index of the entry
+    is treated as a resource handle that is returned to the user. The
+    user is then able to use the handle to reference the LUN during I/O.
+
+    By default, the virtual LUN is created with a size of 0. The user
+    would need to use the DK_CXLFLASH_VLUN_RESIZE ioctl to adjust the grow
+    the virtual LUN to a desired size. To avoid having to perform this
+    resize for the initial creation of the virtual LUN, the user has the
+    option of specifying a size as part of the DK_CXLFLASH_USER_VIRTUAL
+    ioctl, such that when success is returned to the user, the
+    resource handle that is provided is already referencing provisioned
+    storage. This is reflected by the last LBA being a non-zero value.
+
+    When a LUN is accessible from more than one port, this ioctl will
+    return with the DK_CXLFLASH_ALL_PORTS_ACTIVE return flag set. This
+    provides the user with a hint that I/O can be retried in the event
+    of an I/O error as the LUN can be reached over multiple paths.
+
+DK_CXLFLASH_VLUN_RESIZE
+-----------------------
+    This ioctl is responsible for resizing a previously created virtual
+    LUN and will fail if invoked upon a LUN that is not in virtual
+    mode. Upon success, an updated last LBA is returned to the user
+    indicating the new size of the virtual LUN associated with the
+    resource handle.
+
+    The partitioning of virtual LUNs is jointly mediated by the cxlflash
+    driver and the AFU. An allocation table is kept for each LUN that is
+    operating in the virtual mode and used to program a LUN translation
+    table that the AFU references when provided with a resource handle.
+
+    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
+    In addition to returning a failure to user, cxlflash will also schedule
+    an asynchronous AFU reset. Should the user choose to retry the operation,
+    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
+    can either retry the operation or treat it as a failure.
+
+DK_CXLFLASH_RELEASE
+-------------------
+    This ioctl is responsible for releasing a previously obtained
+    reference to either a physical or virtual LUN. This can be
+    thought of as the inverse of the DK_CXLFLASH_USER_DIRECT or
+    DK_CXLFLASH_USER_VIRTUAL ioctls. Upon success, the resource handle
+    is no longer valid and the entry in the resource handle table is
+    made available to be used again.
+
+    As part of the release process for virtual LUNs, the virtual LUN
+    is first resized to 0 to clear out and free the translation tables
+    associated with the virtual LUN reference.
+
+DK_CXLFLASH_DETACH
+------------------
+    This ioctl is responsible for unregistering a context with the
+    cxlflash driver and release outstanding resources that were
+    not explicitly released via the DK_CXLFLASH_RELEASE ioctl. Upon
+    success, all "tokens" which had been provided to the user from the
+    DK_CXLFLASH_ATTACH onward are no longer valid.
+
+    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
+    attach, the application _must_ close the fd2 associated with the context
+    following the detach of the final user of the context.
+
+DK_CXLFLASH_VLUN_CLONE
+----------------------
+    This ioctl is responsible for cloning a previously created
+    context to a more recently created context. It exists solely to
+    support maintaining user space access to storage after a process
+    forks. Upon success, the child process (which invoked the ioctl)
+    will have access to the same LUNs via the same resource handle(s)
+    as the parent, but under a different context.
+
+    Context sharing across processes is not supported with CXL and
+    therefore each fork must be met with establishing a new context
+    for the child process. This ioctl simplifies the state management
+    and playback required by a user in such a scenario. When a process
+    forks, child process can clone the parents context by first creating
+    a context (via DK_CXLFLASH_ATTACH) and then using this ioctl to
+    perform the clone from the parent to the child.
+
+    The clone itself is fairly simple. The resource handle and lun
+    translation tables are copied from the parent context to the child's
+    and then synced with the AFU.
+
+    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
+    attach, the application _must_ close the fd2 associated with the source
+    context (still resident/accessible in the parent process) following the
+    clone. This is to avoid a stale entry in the file descriptor table of the
+    child process.
+
+    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
+    In addition to returning a failure to user, cxlflash will also schedule
+    an asynchronous AFU reset. Should the user choose to retry the operation,
+    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
+    can either retry the operation or treat it as a failure.
+
+DK_CXLFLASH_VERIFY
+------------------
+    This ioctl is used to detect various changes such as the capacity of
+    the disk changing, the number of LUNs visible changing, etc. In cases
+    where the changes affect the application (such as a LUN resize), the
+    cxlflash driver will report the changed state to the application.
+
+    The user calls in when they want to validate that a LUN hasn't been
+    changed in response to a check condition. As the user is operating out
+    of band from the kernel, they will see these types of events without
+    the kernel's knowledge. When encountered, the user's architected
+    behavior is to call in to this ioctl, indicating what they want to
+    verify and passing along any appropriate information. For now, only
+    verifying a LUN change (ie: size different) with sense data is
+    supported.
+
+DK_CXLFLASH_RECOVER_AFU
+-----------------------
+    This ioctl is used to drive recovery (if such an action is warranted)
+    of a specified user context. Any state associated with the user context
+    is re-established upon successful recovery.
+
+    User contexts are put into an error condition when the device needs to
+    be reset or is terminating. Users are notified of this error condition
+    by seeing all 0xF's on an MMIO read. Upon encountering this, the
+    architected behavior for a user is to call into this ioctl to recover
+    their context. A user may also call into this ioctl at any time to
+    check if the device is operating normally. If a failure is returned
+    from this ioctl, the user is expected to gracefully clean up their
+    context via release/detach ioctls. Until they do, the context they
+    hold is not relinquished. The user may also optionally exit the process
+    at which time the context/resources they held will be freed as part of
+    the release fop.
+
+    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
+    attach, the application _must_ unmap and close the fd2 associated with the
+    original context following this ioctl returning success and indicating that
+    the context was recovered (DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET).
+
+DK_CXLFLASH_MANAGE_LUN
+----------------------
+    This ioctl is used to switch a LUN from a mode where it is available
+    for file-system access (legacy), to a mode where it is set aside for
+    exclusive user space access (superpipe). In case a LUN is visible
+    across multiple ports and adapters, this ioctl is used to uniquely
+    identify each LUN by its World Wide Node Name (WWNN).
+
+
+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/*`.
+
+    Applications can be written to perform various functions using the
+    host ioctl APIs below.
+
+    The structure definitions for these IOCTLs are available in:
+    uapi/scsi/cxlflash_ioctl.h
+
+HT_CXLFLASH_LUN_PROVISION
+-------------------------
+    This ioctl is used to create and delete persistent LUNs on cxlflash
+    devices that lack an external LUN management interface. It is only
+    valid when used with AFUs that support the LUN provision capability.
+
+    When sufficient space is available, LUNs can be created by specifying
+    the target port to host the LUN and a desired size in 4K blocks. Upon
+    success, the LUN ID and WWID of the created LUN will be returned and
+    the SCSI bus can be scanned to detect the change in LUN topology. Note
+    that partial allocations are not supported. Should a creation fail due
+    to a space issue, the target port can be queried for its current LUN
+    geometry.
+
+    To remove a LUN, the device must first be disassociated from the Linux
+    SCSI subsystem. The LUN deletion can then be initiated by specifying a
+    target port and LUN ID. Upon success, the LUN geometry associated with
+    the port will be updated to reflect new number of provisioned LUNs and
+    available capacity.
+
+    To query the LUN geometry of a port, the target port is specified and
+    upon success, the following information is presented:
+
+        - Maximum number of provisioned LUNs allowed for the port
+        - Current number of provisioned LUNs for the port
+        - Maximum total capacity of provisioned LUNs for the port (4K blocks)
+        - Current total capacity of provisioned LUNs for the port (4K blocks)
+
+    With this information, the number of available LUNs and capacity can be
+    can be calculated.
+
+HT_CXLFLASH_AFU_DEBUG
+---------------------
+    This ioctl is used to debug AFUs by supporting a command pass-through
+    interface. It is only valid when used with AFUs that support the AFU
+    debug capability.
+
+    With exception of buffer management, AFU debug commands are opaque to
+    cxlflash and treated as pass-through. For debug commands that do require
+    data transfer, the user supplies an adequately sized data buffer and must
+    specify the data transfer direction with respect to the host. There is a
+    maximum transfer size of 256K imposed. Note that partial read completions
+    are not supported - when errors are experienced with a host read data
+    transfer, the data buffer is not copied back to the user.
diff --git a/Documentation/powerpc/cxlflash.txt b/Documentation/powerpc/cxlflash.txt
deleted file mode 100644 (file)
index a64bdaa..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-Introduction
-============
-
-    The IBM Power architecture provides support for CAPI (Coherent
-    Accelerator Power Interface), which is available to certain PCIe slots
-    on Power 8 systems. CAPI can be thought of as a special tunneling
-    protocol through PCIe that allow PCIe adapters to look like special
-    purpose co-processors which can read or write an application's
-    memory and generate page faults. As a result, the host interface to
-    an adapter running in CAPI mode does not require the data buffers to
-    be mapped to the device's memory (IOMMU bypass) nor does it require
-    memory to be pinned.
-
-    On Linux, Coherent Accelerator (CXL) kernel services present CAPI
-    devices as a PCI device by implementing a virtual PCI host bridge.
-    This abstraction simplifies the infrastructure and programming
-    model, allowing for drivers to look similar to other native PCI
-    device drivers.
-
-    CXL provides a mechanism by which user space applications can
-    directly talk to a device (network or storage) bypassing the typical
-    kernel/device driver stack. The CXL Flash Adapter Driver enables a
-    user space application direct access to Flash storage.
-
-    The CXL Flash Adapter Driver is a kernel module that sits in the
-    SCSI stack as a low level device driver (below the SCSI disk and
-    protocol drivers) for the IBM CXL Flash Adapter. This driver is
-    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.
-
-    The cxlflash driver supports two, mutually exclusive, modes of
-    operation at the device (LUN) level:
-
-        - Any flash device (LUN) can be configured to be accessed as a
-          regular disk device (i.e.: /dev/sdc). This is the default mode.
-
-        - Any flash device (LUN) can be configured to be accessed from
-          user space with a special block library. This mode further
-          specifies the means of accessing the device and provides for
-          either raw access to the entire LUN (referred to as direct
-          or physical LUN access) or access to a kernel/AFU-mediated
-          partition of the LUN (referred to as virtual LUN access). The
-          segmentation of a disk device into virtual LUNs is assisted
-          by special translation services provided by the Flash AFU.
-
-Overview
-========
-
-    The Coherent Accelerator Interface Architecture (CAIA) introduces a
-    concept of a master context. A master typically has special privileges
-    granted to it by the kernel or hypervisor allowing it to perform AFU
-    wide management and control. The master may or may not be involved
-    directly in each user I/O, but at the minimum is involved in the
-    initial setup before the user application is allowed to send requests
-    directly to the AFU.
-
-    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:
-
-                     +-------------------------------+
-                     |    512 * 64 KB User MMIO      |
-                     |        (per context)          |
-                     |       User Accessible         |
-                     +-------------------------------+
-                     |    512 * 128 B per context    |
-                     |    Provisioning and Control   |
-                     |   Trusted Process accessible  |
-                     +-------------------------------+
-                     |         64 KB Global          |
-                     |   Trusted Process accessible  |
-                     +-------------------------------+
-
-    This driver configures itself into the SCSI software stack as an
-    adapter driver. The driver is the only entity that is considered a
-    Trusted Process to program the Provisioning and Control and Global
-    areas in the MMIO Space shown above.  The master context driver
-    discovers all LUNs attached to the CXL Flash adapter and instantiates
-    scsi block devices (/dev/sdb, /dev/sdc etc.) for each unique LUN
-    seen from each path.
-
-    Once these scsi block devices are instantiated, an application
-    written to a specification provided by the block library may get
-    access to the Flash from user space (without requiring a system call).
-
-    This master context driver also provides a series of ioctls for this
-    block library to enable this user space access.  The driver supports
-    two modes for accessing the block device.
-
-    The first mode is called a virtual mode. In this mode a single scsi
-    block device (/dev/sdb) may be carved up into any number of distinct
-    virtual LUNs. The virtual LUNs may be resized as long as the sum of
-    the sizes of all the virtual LUNs, along with the meta-data associated
-    with it does not exceed the physical capacity.
-
-    The second mode is called the physical mode. In this mode a single
-    block device (/dev/sdb) may be opened directly by the block library
-    and the entire space for the LUN is available to the application.
-
-    Only the physical mode provides persistence of the data.  i.e. The
-    data written to the block device will survive application exit and
-    restart and also reboot. The virtual LUNs do not persist (i.e. do
-    not survive after the application terminates or the system reboots).
-
-
-Block library API
-=================
-
-    Applications intending to get access to the CXL Flash from user
-    space should use the block library, as it abstracts the details of
-    interfacing directly with the cxlflash driver that are necessary for
-    performing administrative actions (i.e.: setup, tear down, resize).
-    The block library can be thought of as a 'user' of services,
-    implemented as IOCTLs, that are provided by the cxlflash driver
-    specifically for devices (LUNs) operating in user space access
-    mode. While it is not a requirement that applications understand
-    the interface between the block library and the cxlflash driver,
-    a high-level overview of each supported service (IOCTL) is provided
-    below.
-
-    The block library can be found on GitHub:
-    http://github.com/open-power/capiflash
-
-
-CXL Flash Driver LUN IOCTLs
-===========================
-
-    Users, such as the block library, that wish to interface with a flash
-    device (LUN) via user space access need to use the services provided
-    by the cxlflash driver. As these services are implemented as ioctls,
-    a file descriptor handle must first be obtained in order to establish
-    the communication channel between a user and the kernel.  This file
-    descriptor is obtained by opening the device special file associated
-    with the scsi disk device (/dev/sdb) that was created during LUN
-    discovery. As per the location of the cxlflash driver within the
-    SCSI protocol stack, this open is actually not seen by the cxlflash
-    driver. Upon successful open, the user receives a file descriptor
-    (herein referred to as fd1) that should be used for issuing the
-    subsequent ioctls listed below.
-
-    The structure definitions for these IOCTLs are available in:
-    uapi/scsi/cxlflash_ioctl.h
-
-DK_CXLFLASH_ATTACH
-------------------
-
-    This ioctl obtains, initializes, and starts a context using the CXL
-    kernel services. These services specify a context id (u16) by which
-    to uniquely identify the context and its allocated resources. The
-    services additionally provide a second file descriptor (herein
-    referred to as fd2) that is used by the block library to initiate
-    memory mapped I/O (via mmap()) to the CXL flash device and poll for
-    completion events. This file descriptor is intentionally installed by
-    this driver and not the CXL kernel services to allow for intermediary
-    notification and access in the event of a non-user-initiated close(),
-    such as a killed process. This design point is described in further
-    detail in the description for the DK_CXLFLASH_DETACH ioctl.
-
-    There are a few important aspects regarding the "tokens" (context id
-    and fd2) that are provided back to the user:
-
-        - These tokens are only valid for the process under which they
-          were created. The child of a forked process cannot continue
-          to use the context id or file descriptor created by its parent
-          (see DK_CXLFLASH_VLUN_CLONE for further details).
-
-        - These tokens are only valid for the lifetime of the context and
-          the process under which they were created. Once either is
-          destroyed, the tokens are to be considered stale and subsequent
-          usage will result in errors.
-
-       - A valid adapter file descriptor (fd2 >= 0) is only returned on
-         the initial attach for a context. Subsequent attaches to an
-         existing context (DK_CXLFLASH_ATTACH_REUSE_CONTEXT flag present)
-         do not provide the adapter file descriptor as it was previously
-         made known to the application.
-
-        - When a context is no longer needed, the user shall detach from
-          the context via the DK_CXLFLASH_DETACH ioctl. When this ioctl
-         returns with a valid adapter file descriptor and the return flag
-         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
-         close the adapter file descriptor following a successful detach.
-
-       - When this ioctl returns with a valid fd2 and the return flag
-         DK_CXLFLASH_APP_CLOSE_ADAP_FD is present, the application _must_
-         close fd2 in the following circumstances:
-
-               + Following a successful detach of the last user of the context
-               + Following a successful recovery on the context's original fd2
-               + In the child process of a fork(), following a clone ioctl,
-                 on the fd2 associated with the source context
-
-        - At any time, a close on fd2 will invalidate the tokens. Applications
-         should exercise caution to only close fd2 when appropriate (outlined
-         in the previous bullet) to avoid premature loss of I/O.
-
-DK_CXLFLASH_USER_DIRECT
------------------------
-    This ioctl is responsible for transitioning the LUN to direct
-    (physical) mode access and configuring the AFU for direct access from
-    user space on a per-context basis. Additionally, the block size and
-    last logical block address (LBA) are returned to the user.
-
-    As mentioned previously, when operating in user space access mode,
-    LUNs may be accessed in whole or in part. Only one mode is allowed
-    at a time and if one mode is active (outstanding references exist),
-    requests to use the LUN in a different mode are denied.
-
-    The AFU is configured for direct access from user space by adding an
-    entry to the AFU's resource handle table. The index of the entry is
-    treated as a resource handle that is returned to the user. The user
-    is then able to use the handle to reference the LUN during I/O.
-
-DK_CXLFLASH_USER_VIRTUAL
-------------------------
-    This ioctl is responsible for transitioning the LUN to virtual mode
-    of access and configuring the AFU for virtual access from user space
-    on a per-context basis. Additionally, the block size and last logical
-    block address (LBA) are returned to the user.
-
-    As mentioned previously, when operating in user space access mode,
-    LUNs may be accessed in whole or in part. Only one mode is allowed
-    at a time and if one mode is active (outstanding references exist),
-    requests to use the LUN in a different mode are denied.
-
-    The AFU is configured for virtual access from user space by adding
-    an entry to the AFU's resource handle table. The index of the entry
-    is treated as a resource handle that is returned to the user. The
-    user is then able to use the handle to reference the LUN during I/O.
-
-    By default, the virtual LUN is created with a size of 0. The user
-    would need to use the DK_CXLFLASH_VLUN_RESIZE ioctl to adjust the grow
-    the virtual LUN to a desired size. To avoid having to perform this
-    resize for the initial creation of the virtual LUN, the user has the
-    option of specifying a size as part of the DK_CXLFLASH_USER_VIRTUAL
-    ioctl, such that when success is returned to the user, the
-    resource handle that is provided is already referencing provisioned
-    storage. This is reflected by the last LBA being a non-zero value.
-
-    When a LUN is accessible from more than one port, this ioctl will
-    return with the DK_CXLFLASH_ALL_PORTS_ACTIVE return flag set. This
-    provides the user with a hint that I/O can be retried in the event
-    of an I/O error as the LUN can be reached over multiple paths.
-
-DK_CXLFLASH_VLUN_RESIZE
------------------------
-    This ioctl is responsible for resizing a previously created virtual
-    LUN and will fail if invoked upon a LUN that is not in virtual
-    mode. Upon success, an updated last LBA is returned to the user
-    indicating the new size of the virtual LUN associated with the
-    resource handle.
-
-    The partitioning of virtual LUNs is jointly mediated by the cxlflash
-    driver and the AFU. An allocation table is kept for each LUN that is
-    operating in the virtual mode and used to program a LUN translation
-    table that the AFU references when provided with a resource handle.
-
-    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
-    In addition to returning a failure to user, cxlflash will also schedule
-    an asynchronous AFU reset. Should the user choose to retry the operation,
-    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
-    can either retry the operation or treat it as a failure.
-
-DK_CXLFLASH_RELEASE
--------------------
-    This ioctl is responsible for releasing a previously obtained
-    reference to either a physical or virtual LUN. This can be
-    thought of as the inverse of the DK_CXLFLASH_USER_DIRECT or
-    DK_CXLFLASH_USER_VIRTUAL ioctls. Upon success, the resource handle
-    is no longer valid and the entry in the resource handle table is
-    made available to be used again.
-
-    As part of the release process for virtual LUNs, the virtual LUN
-    is first resized to 0 to clear out and free the translation tables
-    associated with the virtual LUN reference.
-
-DK_CXLFLASH_DETACH
-------------------
-    This ioctl is responsible for unregistering a context with the
-    cxlflash driver and release outstanding resources that were
-    not explicitly released via the DK_CXLFLASH_RELEASE ioctl. Upon
-    success, all "tokens" which had been provided to the user from the
-    DK_CXLFLASH_ATTACH onward are no longer valid.
-
-    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
-    attach, the application _must_ close the fd2 associated with the context
-    following the detach of the final user of the context.
-
-DK_CXLFLASH_VLUN_CLONE
-----------------------
-    This ioctl is responsible for cloning a previously created
-    context to a more recently created context. It exists solely to
-    support maintaining user space access to storage after a process
-    forks. Upon success, the child process (which invoked the ioctl)
-    will have access to the same LUNs via the same resource handle(s)
-    as the parent, but under a different context.
-
-    Context sharing across processes is not supported with CXL and
-    therefore each fork must be met with establishing a new context
-    for the child process. This ioctl simplifies the state management
-    and playback required by a user in such a scenario. When a process
-    forks, child process can clone the parents context by first creating
-    a context (via DK_CXLFLASH_ATTACH) and then using this ioctl to
-    perform the clone from the parent to the child.
-
-    The clone itself is fairly simple. The resource handle and lun
-    translation tables are copied from the parent context to the child's
-    and then synced with the AFU.
-
-    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
-    attach, the application _must_ close the fd2 associated with the source
-    context (still resident/accessible in the parent process) following the
-    clone. This is to avoid a stale entry in the file descriptor table of the
-    child process.
-
-    This ioctl can return -EAGAIN if an AFU sync operation takes too long.
-    In addition to returning a failure to user, cxlflash will also schedule
-    an asynchronous AFU reset. Should the user choose to retry the operation,
-    it is expected to succeed. If this ioctl fails with -EAGAIN, the user
-    can either retry the operation or treat it as a failure.
-
-DK_CXLFLASH_VERIFY
-------------------
-    This ioctl is used to detect various changes such as the capacity of
-    the disk changing, the number of LUNs visible changing, etc. In cases
-    where the changes affect the application (such as a LUN resize), the
-    cxlflash driver will report the changed state to the application.
-
-    The user calls in when they want to validate that a LUN hasn't been
-    changed in response to a check condition. As the user is operating out
-    of band from the kernel, they will see these types of events without
-    the kernel's knowledge. When encountered, the user's architected
-    behavior is to call in to this ioctl, indicating what they want to
-    verify and passing along any appropriate information. For now, only
-    verifying a LUN change (ie: size different) with sense data is
-    supported.
-
-DK_CXLFLASH_RECOVER_AFU
------------------------
-    This ioctl is used to drive recovery (if such an action is warranted)
-    of a specified user context. Any state associated with the user context
-    is re-established upon successful recovery.
-
-    User contexts are put into an error condition when the device needs to
-    be reset or is terminating. Users are notified of this error condition
-    by seeing all 0xF's on an MMIO read. Upon encountering this, the
-    architected behavior for a user is to call into this ioctl to recover
-    their context. A user may also call into this ioctl at any time to
-    check if the device is operating normally. If a failure is returned
-    from this ioctl, the user is expected to gracefully clean up their
-    context via release/detach ioctls. Until they do, the context they
-    hold is not relinquished. The user may also optionally exit the process
-    at which time the context/resources they held will be freed as part of
-    the release fop.
-
-    When the DK_CXLFLASH_APP_CLOSE_ADAP_FD flag was returned on a successful
-    attach, the application _must_ unmap and close the fd2 associated with the
-    original context following this ioctl returning success and indicating that
-    the context was recovered (DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET).
-
-DK_CXLFLASH_MANAGE_LUN
-----------------------
-    This ioctl is used to switch a LUN from a mode where it is available
-    for file-system access (legacy), to a mode where it is set aside for
-    exclusive user space access (superpipe). In case a LUN is visible
-    across multiple ports and adapters, this ioctl is used to uniquely
-    identify each LUN by its World Wide Node Name (WWNN).
-
-
-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/*.
-
-    Applications can be written to perform various functions using the
-    host ioctl APIs below.
-
-    The structure definitions for these IOCTLs are available in:
-    uapi/scsi/cxlflash_ioctl.h
-
-HT_CXLFLASH_LUN_PROVISION
--------------------------
-    This ioctl is used to create and delete persistent LUNs on cxlflash
-    devices that lack an external LUN management interface. It is only
-    valid when used with AFUs that support the LUN provision capability.
-
-    When sufficient space is available, LUNs can be created by specifying
-    the target port to host the LUN and a desired size in 4K blocks. Upon
-    success, the LUN ID and WWID of the created LUN will be returned and
-    the SCSI bus can be scanned to detect the change in LUN topology. Note
-    that partial allocations are not supported. Should a creation fail due
-    to a space issue, the target port can be queried for its current LUN
-    geometry.
-
-    To remove a LUN, the device must first be disassociated from the Linux
-    SCSI subsystem. The LUN deletion can then be initiated by specifying a
-    target port and LUN ID. Upon success, the LUN geometry associated with
-    the port will be updated to reflect new number of provisioned LUNs and
-    available capacity.
-
-    To query the LUN geometry of a port, the target port is specified and
-    upon success, the following information is presented:
-
-        - Maximum number of provisioned LUNs allowed for the port
-        - Current number of provisioned LUNs for the port
-        - Maximum total capacity of provisioned LUNs for the port (4K blocks)
-        - Current total capacity of provisioned LUNs for the port (4K blocks)
-
-    With this information, the number of available LUNs and capacity can be
-    can be calculated.
-
-HT_CXLFLASH_AFU_DEBUG
----------------------
-    This ioctl is used to debug AFUs by supporting a command pass-through
-    interface. It is only valid when used with AFUs that support the AFU
-    debug capability.
-
-    With exception of buffer management, AFU debug commands are opaque to
-    cxlflash and treated as pass-through. For debug commands that do require
-    data transfer, the user supplies an adequately sized data buffer and must
-    specify the data transfer direction with respect to the host. There is a
-    maximum transfer size of 256K imposed. Note that partial read completions
-    are not supported - when errors are experienced with a host read data
-    transfer, the data buffer is not copied back to the user.
diff --git a/Documentation/powerpc/dawr-power9.rst b/Documentation/powerpc/dawr-power9.rst
new file mode 100644 (file)
index 0000000..c96ab6b
--- /dev/null
@@ -0,0 +1,93 @@
+=====================
+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::
+
+    commit 9654153158d3e0684a1bdb76dbababdb7111d5a0
+    Author: Michael Neuling <mikey@neuling.org>
+    Date:   Tue Mar 27 15:37:24 2018 +1100
+    powerpc: Disable DAWR in the base POWER9 CPU features
+
+Technical Details:
+==================
+
+DAWR has 6 different ways of being set.
+1) ptrace
+2) h_set_mode(DAWR)
+3) h_set_dabr()
+4) kvmppc_set_one_reg()
+5) xmon
+
+For ptrace, we now advertise zero breakpoints on POWER9 via the
+PPC_PTRACE_GETHWDBGINFO call. This results in GDB falling back to
+software emulation of the watchpoint (which is slow).
+
+h_set_mode(DAWR) and h_set_dabr() will now return an error to the
+guest on a POWER9 host. Current Linux guests ignore this error, so
+they will silently not get the DAWR.
+
+kvmppc_set_one_reg() will store the value in the vcpu but won't
+actually set it on POWER9 hardware. This is done so we don't break
+migration from POWER8 to POWER9, at the cost of silently losing the
+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
+support for the watchpoint, GDB will software emulate the watchpoint
+making it run very slowly.
+
+The same will also be true for any guests started on a POWER9
+host. The watchpoint will fail and GDB will fall back to software
+emulation.
+
+If a guest is started on a POWER8 host, GDB will accept the watchpoint
+and configure the hardware to use the DAWR. This will run at full
+speed since it can use the hardware emulation. Unfortunately if this
+guest is migrated to a POWER9 host, the watchpoint will be lost on the
+POWER9. Loads and stores to the watchpoint locations will not be
+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::
+
+  echo Y > /sys/kernel/debug/powerpc/dawr_enable_dangerous
+
+This enables the DAWR even on POWER9.
+
+This is a dangerous setting, USE AT YOUR OWN RISK.
+
+Some users may not care about a bad user crashing their box
+(ie. single user/desktop systems) and really want the DAWR.  This
+allows them to force enable DAWR.
+
+This flag can also be used to disable DAWR access. Once this is
+cleared, all DAWR access should be cleared immediately and your
+machine once again safe from crashing.
+
+Userspace may get confused by toggling this. If DAWR is force
+enabled/disabled between getting the number of breakpoints (via
+PTRACE_GETHWDBGINFO) and setting the breakpoint, userspace will get an
+inconsistent view of what's available. Similarly for guests.
+
+For the DAWR to be enabled in a KVM guest, the DAWR needs to be force
+enabled in the host AND the guest. For this reason, this won't work on
+POWERVM as it doesn't allow the HCALL to work. Writes of 'Y' to the
+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.rst b/Documentation/powerpc/dscr.rst
new file mode 100644 (file)
index 0000000..2ab9900
--- /dev/null
@@ -0,0 +1,87 @@
+===================================
+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
+for more detailed information regarding how to use this DSCR to attain this
+control of the prefetches . This document here provides an overview of kernel
+support for DSCR, related kernel objects, it's functionalities and exported
+user interface.
+
+(A) Data Structures:
+
+       (1) thread_struct::
+
+               dscr            /* Thread DSCR value */
+               dscr_inherit    /* Thread has changed default DSCR */
+
+       (2) PACA::
+
+               dscr_default    /* per-CPU DSCR default value */
+
+       (3) sysfs.c::
+
+               dscr_default    /* System DSCR default value */
+
+(B) Scheduler Changes:
+
+       Scheduler will write the per-CPU DSCR default which is stored in the
+       CPU's PACA value into the register if the thread has dscr_inherit value
+       cleared which means that it has not changed the default DSCR till now.
+       If the dscr_inherit value is set which means that it has changed the
+       default DSCR value, scheduler will write the changed value which will
+       now be contained in thread struct's dscr into the register instead of
+       the per-CPU default PACA based DSCR value.
+
+       NOTE: Please note here that the system wide global DSCR value never
+       gets used directly in the scheduler process context switch at all.
+
+(C) SYSFS Interface:
+
+       - 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
+       the current process has the dscr_inherit clear, it also writes the new
+       value into every CPU's DSCR register right away and updates the current
+       thread's DSCR value as well.
+
+       Changing the CPU specific DSCR default value in the sysfs does exactly
+       the same thing as above but unlike the global one above, it just changes
+       stuff for that particular CPU instead for all the CPUs on the system.
+
+(D) User Space Instructions:
+
+       The DSCR register can be accessed in the user space using any of these
+       two SPR numbers available for that purpose.
+
+       (1) Problem state SPR:          0x03    (Un-privileged, POWER8 only)
+       (2) Privileged state SPR:       0x11    (Privileged)
+
+       Accessing DSCR through privileged SPR number (0x11) from user space
+       works, as it is emulated following an illegal instruction exception
+       inside the kernel. Both mfspr and mtspr instructions are emulated.
+
+       Accessing DSCR through user level SPR (0x03) from user space will first
+       create a facility unavailable exception. Inside this exception handler
+       all mfspr instruction based read attempts will get emulated and returned
+       where as the first mtspr instruction based write attempts will enable
+       the DSCR facility for the next time around (both for read and write) by
+       setting DSCR facility in the FSCR register.
+
+(E) Specifics about 'dscr_inherit':
+
+       The thread struct element 'dscr_inherit' represents whether the thread
+       in question has attempted and changed the DSCR itself using any of the
+       following methods. This element signifies whether the thread wants to
+       use the CPU default DSCR value or its own changed DSCR value in the
+       kernel.
+
+               (1) mtspr instruction   (SPR number 0x03)
+               (2) mtspr instruction   (SPR number 0x11)
+               (3) ptrace interface    (Explicitly set user DSCR value)
+
+       Any child of the process created after this event in the process inherits
+       this same behaviour as well.
diff --git a/Documentation/powerpc/dscr.txt b/Documentation/powerpc/dscr.txt
deleted file mode 100644 (file)
index ece300c..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-                       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
-for more detailed information regarding how to use this DSCR to attain this
-control of the prefetches . This document here provides an overview of kernel
-support for DSCR, related kernel objects, it's functionalities and exported
-user interface.
-
-(A) Data Structures:
-
-       (1) thread_struct:
-               dscr            /* Thread DSCR value */
-               dscr_inherit    /* Thread has changed default DSCR */
-
-       (2) PACA:
-               dscr_default    /* per-CPU DSCR default value */
-
-       (3) sysfs.c:
-               dscr_default    /* System DSCR default value */
-
-(B) Scheduler Changes:
-
-       Scheduler will write the per-CPU DSCR default which is stored in the
-       CPU's PACA value into the register if the thread has dscr_inherit value
-       cleared which means that it has not changed the default DSCR till now.
-       If the dscr_inherit value is set which means that it has changed the
-       default DSCR value, scheduler will write the changed value which will
-       now be contained in thread struct's dscr into the register instead of
-       the per-CPU default PACA based DSCR value.
-
-       NOTE: Please note here that the system wide global DSCR value never
-       gets used directly in the scheduler process context switch at all.
-
-(C) SYSFS Interface:
-
-       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
-       the current process has the dscr_inherit clear, it also writes the new
-       value into every CPU's DSCR register right away and updates the current
-       thread's DSCR value as well.
-
-       Changing the CPU specific DSCR default value in the sysfs does exactly
-       the same thing as above but unlike the global one above, it just changes
-       stuff for that particular CPU instead for all the CPUs on the system.
-
-(D) User Space Instructions:
-
-       The DSCR register can be accessed in the user space using any of these
-       two SPR numbers available for that purpose.
-
-       (1) Problem state SPR:          0x03    (Un-privileged, POWER8 only)
-       (2) Privileged state SPR:       0x11    (Privileged)
-
-       Accessing DSCR through privileged SPR number (0x11) from user space
-       works, as it is emulated following an illegal instruction exception
-       inside the kernel. Both mfspr and mtspr instructions are emulated.
-
-       Accessing DSCR through user level SPR (0x03) from user space will first
-       create a facility unavailable exception. Inside this exception handler
-       all mfspr instruction based read attempts will get emulated and returned
-       where as the first mtspr instruction based write attempts will enable
-       the DSCR facility for the next time around (both for read and write) by
-       setting DSCR facility in the FSCR register.
-
-(E) Specifics about 'dscr_inherit':
-
-       The thread struct element 'dscr_inherit' represents whether the thread
-       in question has attempted and changed the DSCR itself using any of the
-       following methods. This element signifies whether the thread wants to
-       use the CPU default DSCR value or its own changed DSCR value in the
-       kernel.
-
-               (1) mtspr instruction   (SPR number 0x03)
-               (2) mtspr instruction   (SPR number 0x11)
-               (3) ptrace interface    (Explicitly set user DSCR value)
-
-       Any child of the process created after this event in the process inherits
-       this same behaviour as well.
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.rst b/Documentation/powerpc/eeh-pci-error-recovery.rst
new file mode 100644 (file)
index 0000000..438a87e
--- /dev/null
@@ -0,0 +1,336 @@
+==========================
+PCI Bus EEH Error Recovery
+==========================
+
+Linas Vepstas <linas@austin.ibm.com>
+
+12 January 2005
+
+
+Overview:
+---------
+The IBM POWER-based pSeries and iSeries computers include PCI bus
+controller chips that have extended capabilities for detecting and
+reporting a large variety of PCI bus error conditions.  These features
+go under the name of "EEH", for "Enhanced Error Handling".  The EEH
+hardware features allow PCI bus errors to be cleared and a PCI
+card to be "rebooted", without also having to reboot the operating
+system.
+
+This is in contrast to traditional PCI error handling, where the
+PCI chip is wired directly to the CPU, and an error would cause
+a CPU machine-check/check-stop condition, halting the CPU entirely.
+Another "traditional" technique is to ignore such errors, which
+can lead to data corruption, both of user data or of kernel data,
+hung/unresponsive adapters, or system crashes/lockups.  Thus,
+the idea behind EEH is that the operating system can become more
+reliable and robust by protecting it from PCI errors, and giving
+the OS the ability to "reboot"/recover individual PCI devices.
+
+Future systems from other vendors, based on the PCI-E specification,
+may contain similar features.
+
+
+Causes of EEH Errors
+--------------------
+EEH was originally designed to guard against hardware failure, such
+as PCI cards dying from heat, humidity, dust, vibration and bad
+electrical connections. The vast majority of EEH errors seen in
+"real life" are due to either poorly seated PCI cards, or,
+unfortunately quite commonly, due to device driver bugs, device firmware
+bugs, and sometimes PCI card hardware bugs.
+
+The most common software bug, is one that causes the device to
+attempt to DMA to a location in system memory that has not been
+reserved for DMA access for that card.  This is a powerful feature,
+as it prevents what; otherwise, would have been silent memory
+corruption caused by the bad DMA.  A number of device driver
+bugs have been found and fixed in this way over the past few
+years.  Other possible causes of EEH errors include data or
+address line parity errors (for example, due to poor electrical
+connectivity due to a poorly seated card), and PCI-X split-completion
+errors (due to software, device firmware, or device PCI hardware bugs).
+The vast majority of "true hardware failures" can be cured by
+physically removing and re-seating the PCI card.
+
+
+Detection and Recovery
+----------------------
+In the following discussion, a generic overview of how to detect
+and recover from EEH errors will be presented. This is followed
+by an overview of how the current implementation in the Linux
+kernel does it.  The actual implementation is subject to change,
+and some of the finer points are still being debated.  These
+may in turn be swayed if or when other architectures implement
+similar functionality.
+
+When a PCI Host Bridge (PHB, the bus controller connecting the
+PCI bus to the system CPU electronics complex) detects a PCI error
+condition, it will "isolate" the affected PCI card.  Isolation
+will block all writes (either to the card from the system, or
+from the card to the system), and it will cause all reads to
+return all-ff's (0xff, 0xffff, 0xffffffff for 8/16/32-bit reads).
+This value was chosen because it is the same value you would
+get if the device was physically unplugged from the slot.
+This includes access to PCI memory, I/O space, and PCI config
+space.  Interrupts; however, will continued to be delivered.
+
+Detection and recovery are performed with the aid of ppc64
+firmware.  The programming interfaces in the Linux kernel
+into the firmware are referred to as RTAS (Run-Time Abstraction
+Services).  The Linux kernel does not (should not) access
+the EEH function in the PCI chipsets directly, primarily because
+there are a number of different chipsets out there, each with
+different interfaces and quirks. The firmware provides a
+uniform abstraction layer that will work with all pSeries
+and iSeries hardware (and be forwards-compatible).
+
+If the OS or device driver suspects that a PCI slot has been
+EEH-isolated, there is a firmware call it can make to determine if
+this is the case. If so, then the device driver should put itself
+into a consistent state (given that it won't be able to complete any
+pending work) and start recovery of the card.  Recovery normally
+would consist of resetting the PCI device (holding the PCI #RST
+line high for two seconds), followed by setting up the device
+config space (the base address registers (BAR's), latency timer,
+cache line size, interrupt line, and so on).  This is followed by a
+reinitialization of the device driver.  In a worst-case scenario,
+the power to the card can be toggled, at least on hot-plug-capable
+slots.  In principle, layers far above the device driver probably
+do not need to know that the PCI card has been "rebooted" in this
+way; ideally, there should be at most a pause in Ethernet/disk/USB
+I/O while the card is being reset.
+
+If the card cannot be recovered after three or four resets, the
+kernel/device driver should assume the worst-case scenario, that the
+card has died completely, and report this error to the sysadmin.
+In addition, error messages are reported through RTAS and also through
+syslogd (/var/log/messages) to alert the sysadmin of PCI resets.
+The correct way to deal with failed adapters is to use the standard
+PCI hotplug tools to remove and replace the dead card.
+
+
+Current PPC64 Linux EEH Implementation
+--------------------------------------
+At this time, a generic EEH recovery mechanism has been implemented,
+so that individual device drivers do not need to be modified to support
+EEH recovery.  This generic mechanism piggy-backs on the PCI hotplug
+infrastructure,  and percolates events up through the userspace/udev
+infrastructure.  Following is a detailed description of how this is
+accomplished.
+
+EEH must be enabled in the PHB's very early during the boot process,
+and if a PCI slot is hot-plugged. The former is performed by
+eeh_init() in arch/powerpc/platforms/pseries/eeh.c, and the later by
+drivers/pci/hotplug/pSeries_pci.c calling in to the eeh.c code.
+EEH must be enabled before a PCI scan of the device can proceed.
+Current Power5 hardware will not work unless EEH is enabled;
+although older Power4 can run with it disabled.  Effectively,
+EEH can no longer be turned off.  PCI devices *must* be
+registered with the EEH code; the EEH code needs to know about
+the I/O address ranges of the PCI device in order to detect an
+error.  Given an arbitrary address, the routine
+pci_get_device_by_addr() will find the pci device associated
+with that address (if any).
+
+The default arch/powerpc/include/asm/io.h macros readb(), inb(), insb(),
+etc. include a check to see if the i/o read returned all-0xff's.
+If so, these make a call to eeh_dn_check_failure(), which in turn
+asks the firmware if the all-ff's value is the sign of a true EEH
+error.  If it is not, processing continues as normal.  The grand
+total number of these false alarms or "false positives" can be
+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
+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
+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
+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
+   located topologically under the pci slot.
+eeh_save_bars() and eeh_restore_bars():
+   save and restore the PCI
+   config-space info for a device and any devices under it.
+
+
+A handler for the EEH notifier_block events is implemented in
+drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
+It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
+This last call causes the device driver for the card to be stopped,
+which causes uevents to go out to user space. This triggers
+user-space scripts that might issue commands such as "ifdown eth0"
+for ethernet cards, and so on.  This handler then sleeps for 5 seconds,
+hoping to give the user-space scripts enough time to complete.
+It then resets the PCI card, reconfigures the device BAR's, and
+any bridges underneath. It then calls rpaphp_enable_pci_slot(),
+which restarts the device driver and triggers more user-space
+events (for example, calling "ifup eth0" for ethernet cards).
+
+
+Device Shutdown and User-Space Events
+-------------------------------------
+This section documents what happens when a pci slot is unconfigured,
+focusing on how the device driver gets shut down, and on how the
+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::
+
+    rpa_php_unconfig_pci_adapter (struct slot *)  // in rpaphp_pci.c
+    {
+      calls
+      pci_remove_bus_device (struct pci_dev *) // in /drivers/pci/remove.c
+      {
+        calls
+        pci_destroy_dev (struct pci_dev *)
+        {
+          calls
+          device_unregister (&dev->dev) // in /drivers/base/core.c
+          {
+            calls
+            device_del (struct device *)
+            {
+              calls
+              bus_remove_device() // in /drivers/base/bus.c
+              {
+                calls
+                device_release_driver()
+                {
+                  calls
+                  struct device_driver->remove() which is just
+                  pci_device_remove()  // in /drivers/pci/pci_driver.c
+                  {
+                    calls
+                    struct pci_driver->remove() which is just
+                    pcnet32_remove_one() // in /drivers/net/pcnet32.c
+                    {
+                      calls
+                      unregister_netdev() // in /net/core/dev.c
+                      {
+                        calls
+                        dev_close()  // in /net/core/dev.c
+                        {
+                           calls dev->stop();
+                           which is just pcnet32_close() // in pcnet32.c
+                           {
+                             which does what you wanted
+                             to stop the device
+                           }
+                        }
+                     }
+                   which
+                   frees pcnet32 device driver memory
+                }
+     }}}}}}
+
+
+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::
+
+  rpa_php_unconfig_pci_adapter() {             // in rpaphp_pci.c
+    calls
+    pci_remove_bus_device (struct pci_dev *) { // in /drivers/pci/remove.c
+      calls
+      pci_destroy_dev (struct pci_dev *) {
+        calls
+        device_unregister (&dev->dev) {        // in /drivers/base/core.c
+          calls
+          device_del(struct device * dev) {    // in /drivers/base/core.c
+            calls
+            kobject_del() {                    //in /libs/kobject.c
+              calls
+              kobject_uevent() {               // in /libs/kobject.c
+                calls
+                kset_uevent() {                // in /lib/kobject.c
+                  calls
+                  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)
+             }
+           }
+           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
+-------------------------------------
+There are several issues with the current EEH software recovery design,
+which may be addressed in future revisions.  But first, note that the
+big plus of the current design is that no changes need to be made to
+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
+   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,
+   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,
+   ideally, the reset should happen at or below the block layer,
+   so that the file systems are not disturbed.
+
+   Reiserfs does not tolerate errors returned from the block device.
+   Ext3fs seems to be tolerant, retrying reads/writes until it does
+   succeed. Both have been only lightly tested in this scenario.
+
+   The SCSI-generic subsystem already has built-in code for performing
+   SCSI device resets, SCSI bus resets, and SCSI host-bus-adapter
+   (HBA) resets.  These are cascaded into a chain of attempted
+   resets if a SCSI command fails. These are completely hidden
+   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
+   the sysadmin had the foresight to run /bin, /sbin, /etc, /var
+   and so on, out of ramdisk/tmpfs.
+
+
+Conclusions
+-----------
+There's forward progress ...
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt
deleted file mode 100644 (file)
index 6781892..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-
-
-                      PCI Bus EEH Error Recovery
-                      --------------------------
-                           Linas Vepstas
-                       <linas@austin.ibm.com>
-                          12 January 2005
-
-
-Overview:
----------
-The IBM POWER-based pSeries and iSeries computers include PCI bus
-controller chips that have extended capabilities for detecting and
-reporting a large variety of PCI bus error conditions.  These features
-go under the name of "EEH", for "Enhanced Error Handling".  The EEH
-hardware features allow PCI bus errors to be cleared and a PCI
-card to be "rebooted", without also having to reboot the operating
-system.
-
-This is in contrast to traditional PCI error handling, where the
-PCI chip is wired directly to the CPU, and an error would cause
-a CPU machine-check/check-stop condition, halting the CPU entirely.
-Another "traditional" technique is to ignore such errors, which
-can lead to data corruption, both of user data or of kernel data,
-hung/unresponsive adapters, or system crashes/lockups.  Thus,
-the idea behind EEH is that the operating system can become more
-reliable and robust by protecting it from PCI errors, and giving
-the OS the ability to "reboot"/recover individual PCI devices.
-
-Future systems from other vendors, based on the PCI-E specification,
-may contain similar features.
-
-
-Causes of EEH Errors
---------------------
-EEH was originally designed to guard against hardware failure, such
-as PCI cards dying from heat, humidity, dust, vibration and bad
-electrical connections. The vast majority of EEH errors seen in
-"real life" are due to either poorly seated PCI cards, or,
-unfortunately quite commonly, due to device driver bugs, device firmware
-bugs, and sometimes PCI card hardware bugs.
-
-The most common software bug, is one that causes the device to
-attempt to DMA to a location in system memory that has not been
-reserved for DMA access for that card.  This is a powerful feature,
-as it prevents what; otherwise, would have been silent memory
-corruption caused by the bad DMA.  A number of device driver
-bugs have been found and fixed in this way over the past few
-years.  Other possible causes of EEH errors include data or
-address line parity errors (for example, due to poor electrical
-connectivity due to a poorly seated card), and PCI-X split-completion
-errors (due to software, device firmware, or device PCI hardware bugs).
-The vast majority of "true hardware failures" can be cured by
-physically removing and re-seating the PCI card.
-
-
-Detection and Recovery
-----------------------
-In the following discussion, a generic overview of how to detect
-and recover from EEH errors will be presented. This is followed
-by an overview of how the current implementation in the Linux
-kernel does it.  The actual implementation is subject to change,
-and some of the finer points are still being debated.  These
-may in turn be swayed if or when other architectures implement
-similar functionality.
-
-When a PCI Host Bridge (PHB, the bus controller connecting the
-PCI bus to the system CPU electronics complex) detects a PCI error
-condition, it will "isolate" the affected PCI card.  Isolation
-will block all writes (either to the card from the system, or
-from the card to the system), and it will cause all reads to
-return all-ff's (0xff, 0xffff, 0xffffffff for 8/16/32-bit reads).
-This value was chosen because it is the same value you would
-get if the device was physically unplugged from the slot.
-This includes access to PCI memory, I/O space, and PCI config
-space.  Interrupts; however, will continued to be delivered.
-
-Detection and recovery are performed with the aid of ppc64
-firmware.  The programming interfaces in the Linux kernel
-into the firmware are referred to as RTAS (Run-Time Abstraction
-Services).  The Linux kernel does not (should not) access
-the EEH function in the PCI chipsets directly, primarily because
-there are a number of different chipsets out there, each with
-different interfaces and quirks. The firmware provides a
-uniform abstraction layer that will work with all pSeries
-and iSeries hardware (and be forwards-compatible).
-
-If the OS or device driver suspects that a PCI slot has been
-EEH-isolated, there is a firmware call it can make to determine if
-this is the case. If so, then the device driver should put itself
-into a consistent state (given that it won't be able to complete any
-pending work) and start recovery of the card.  Recovery normally
-would consist of resetting the PCI device (holding the PCI #RST
-line high for two seconds), followed by setting up the device
-config space (the base address registers (BAR's), latency timer,
-cache line size, interrupt line, and so on).  This is followed by a
-reinitialization of the device driver.  In a worst-case scenario,
-the power to the card can be toggled, at least on hot-plug-capable
-slots.  In principle, layers far above the device driver probably
-do not need to know that the PCI card has been "rebooted" in this
-way; ideally, there should be at most a pause in Ethernet/disk/USB
-I/O while the card is being reset.
-
-If the card cannot be recovered after three or four resets, the
-kernel/device driver should assume the worst-case scenario, that the
-card has died completely, and report this error to the sysadmin.
-In addition, error messages are reported through RTAS and also through
-syslogd (/var/log/messages) to alert the sysadmin of PCI resets.
-The correct way to deal with failed adapters is to use the standard
-PCI hotplug tools to remove and replace the dead card.
-
-
-Current PPC64 Linux EEH Implementation
---------------------------------------
-At this time, a generic EEH recovery mechanism has been implemented,
-so that individual device drivers do not need to be modified to support
-EEH recovery.  This generic mechanism piggy-backs on the PCI hotplug
-infrastructure,  and percolates events up through the userspace/udev
-infrastructure.  Following is a detailed description of how this is
-accomplished.
-
-EEH must be enabled in the PHB's very early during the boot process,
-and if a PCI slot is hot-plugged. The former is performed by
-eeh_init() in arch/powerpc/platforms/pseries/eeh.c, and the later by
-drivers/pci/hotplug/pSeries_pci.c calling in to the eeh.c code.
-EEH must be enabled before a PCI scan of the device can proceed.
-Current Power5 hardware will not work unless EEH is enabled;
-although older Power4 can run with it disabled.  Effectively,
-EEH can no longer be turned off.  PCI devices *must* be
-registered with the EEH code; the EEH code needs to know about
-the I/O address ranges of the PCI device in order to detect an
-error.  Given an arbitrary address, the routine
-pci_get_device_by_addr() will find the pci device associated
-with that address (if any).
-
-The default arch/powerpc/include/asm/io.h macros readb(), inb(), insb(),
-etc. include a check to see if the i/o read returned all-0xff's.
-If so, these make a call to eeh_dn_check_failure(), which in turn
-asks the firmware if the all-ff's value is the sign of a true EEH
-error.  If it is not, processing continues as normal.  The grand
-total number of these false alarms or "false positives" can be
-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 
-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
-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
-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
-   located topologically under the pci slot.
-eeh_save_bars() and eeh_restore_bars(): save and restore the PCI
-   config-space info for a device and any devices under it.
-
-
-A handler for the EEH notifier_block events is implemented in
-drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
-It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
-This last call causes the device driver for the card to be stopped,
-which causes uevents to go out to user space. This triggers
-user-space scripts that might issue commands such as "ifdown eth0"
-for ethernet cards, and so on.  This handler then sleeps for 5 seconds,
-hoping to give the user-space scripts enough time to complete.
-It then resets the PCI card, reconfigures the device BAR's, and
-any bridges underneath. It then calls rpaphp_enable_pci_slot(),
-which restarts the device driver and triggers more user-space
-events (for example, calling "ifup eth0" for ethernet cards).
-
-
-Device Shutdown and User-Space Events
--------------------------------------
-This section documents what happens when a pci slot is unconfigured,
-focusing on how the device driver gets shut down, and on how the
-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.
-
-    rpa_php_unconfig_pci_adapter (struct slot *)  // in rpaphp_pci.c
-    {
-      calls
-      pci_remove_bus_device (struct pci_dev *) // in /drivers/pci/remove.c
-      {
-        calls
-        pci_destroy_dev (struct pci_dev *)
-        {
-          calls
-          device_unregister (&dev->dev) // in /drivers/base/core.c
-          {
-            calls
-            device_del (struct device *)
-            {
-              calls
-              bus_remove_device() // in /drivers/base/bus.c
-              {
-                calls
-                device_release_driver()
-                {
-                  calls
-                  struct device_driver->remove() which is just
-                  pci_device_remove()  // in /drivers/pci/pci_driver.c
-                  {
-                    calls
-                    struct pci_driver->remove() which is just
-                    pcnet32_remove_one() // in /drivers/net/pcnet32.c
-                    {
-                      calls
-                      unregister_netdev() // in /net/core/dev.c
-                      {
-                        calls
-                        dev_close()  // in /net/core/dev.c
-                        {
-                           calls dev->stop();
-                           which is just pcnet32_close() // in pcnet32.c
-                           {
-                             which does what you wanted
-                             to stop the device
-                           }
-                        }
-                     }
-                   which
-                   frees pcnet32 device driver memory
-                }
-     }}}}}}
-
-
-    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.
-
-rpa_php_unconfig_pci_adapter() {             // in rpaphp_pci.c
-  calls
-  pci_remove_bus_device (struct pci_dev *) { // in /drivers/pci/remove.c
-    calls
-    pci_destroy_dev (struct pci_dev *) {
-      calls
-      device_unregister (&dev->dev) {        // in /drivers/base/core.c
-        calls
-        device_del(struct device * dev) {    // in /drivers/base/core.c
-          calls
-          kobject_del() {                    //in /libs/kobject.c
-            calls
-            kobject_uevent() {               // in /libs/kobject.c
-              calls
-              kset_uevent() {                // in /lib/kobject.c
-                calls
-                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)
-           }
-         }
-         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
--------------------------------------
-There are several issues with the current EEH software recovery design,
-which may be addressed in future revisions.  But first, note that the
-big plus of the current design is that no changes need to be made to
-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
-   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,
-   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,
-   ideally, the reset should happen at or below the block layer,
-   so that the file systems are not disturbed.
-
-   Reiserfs does not tolerate errors returned from the block device.
-   Ext3fs seems to be tolerant, retrying reads/writes until it does
-   succeed. Both have been only lightly tested in this scenario.
-
-   The SCSI-generic subsystem already has built-in code for performing
-   SCSI device resets, SCSI bus resets, and SCSI host-bus-adapter
-   (HBA) resets.  These are cascaded into a chain of attempted
-   resets if a SCSI command fails. These are completely hidden
-   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
-   the sysadmin had the foresight to run /bin, /sbin, /etc, /var
-   and so on, out of ramdisk/tmpfs.
-
-
-Conclusions
------------
-There's forward progress ...
-
-
diff --git a/Documentation/powerpc/firmware-assisted-dump.rst b/Documentation/powerpc/firmware-assisted-dump.rst
new file mode 100644 (file)
index 0000000..9ca1283
--- /dev/null
@@ -0,0 +1,301 @@
+======================
+Firmware-Assisted Dump
+======================
+
+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
+to minimize the total elapsed time until the system is back
+in production use.
+
+- Firmware assisted dump (fadump) infrastructure is intended to replace
+  the existing phyp assisted dump.
+- Fadump uses the same firmware interfaces and memory reservation model
+  as phyp assisted dump.
+- Unlike phyp dump, fadump exports the memory dump through /proc/vmcore
+  in the ELF format in the same way as kdump. This helps us reuse the
+  kdump infrastructure for dump capture and filtering.
+- Unlike phyp dump, userspace tool does not need to refer any sysfs
+  interface while reading /proc/vmcore.
+- Unlike phyp dump, fadump allows user to release all the memory reserved
+  for dump, with a single operation of echo 1 > /sys/kernel/fadump_release_mem.
+- Once enabled through kernel boot parameter, fadump can be
+  started/stopped through /sys/kernel/fadump_registered interface (see
+  sysfs files section below) and can be easily integrated with kdump
+  service start/stop init scripts.
+
+Comparing with kdump or other strategies, firmware-assisted
+dump offers several strong, practical advantages:
+
+-  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
+   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.
+
+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
+   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
+   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
+         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.
+         Alternatively, user can also specify boot memory size
+         through boot parameter 'crashkernel=' which will override
+         the default calculated size. Use this option if default
+         boot memory size is not sufficient for second kernel to
+         boot successfully. For syntax of crashkernel= parameter,
+         refer to Documentation/admin-guide/kdump/kdump.rst. If any offset is
+         provided in crashkernel= parameter, it will be ignored
+         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
+   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
+   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
+   boot memory size effectively booting with restricted memory
+   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
+   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
+   '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.::
+
+     # echo 1 > /sys/kernel/fadump_release_mem
+
+Please note that the firmware-assisted dump feature
+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
+we check to see if an active dump is waiting for us. If yes
+then everything but boot memory size of RAM is reserved during
+early boot (See Fig. 2). This area is released once we finish
+collecting the dump from user land scripts (e.g. kdump scripts)
+that are run. If there is dump data, then the
+/sys/kernel/fadump_release_mem file is created, and the reserved
+memory is held.
+
+If there is no waiting dump data, then only the memory required
+to hold CPU state, HPTE region, boot memory dump and elfcore
+header, is usually reserved at an offset greater than boot memory
+size (see Fig. 1). This area is *not* released: this region will
+be kept permanently reserved, so that it can act as a receptacle
+for a copy of the boot memory content in addition to CPU state
+and HPTE region, in the case a crash does occur. Since this reserved
+memory area is used only after the system crash, there is no point in
+blocking this significant chunk of memory from production kernel.
+Hence, the implementation uses the Linux kernel's Contiguous Memory
+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::
+
+  o Memory Reservation during first kernel
+
+  Low memory                                         Top of memory
+  0      boot memory size                                       |
+  |           |                |<--Reserved dump area -->|      |
+  V           V                |   Permanent Reservation |      V
+  +-----------+----------/ /---+---+----+-----------+----+------+
+  |           |                |CPU|HPTE|  DUMP     |ELF |      |
+  +-----------+----------/ /---+---+----+-----------+----+------+
+        |                                           ^
+        |                                           |
+        \                                           /
+         -------------------------------------------
+          Boot memory content gets transferred to
+          reserved area by firmware at the time of
+          crash
+                   Fig. 1
+
+  o Memory Reservation during second kernel after crash
+
+  Low memory                                        Top of memory
+  0      boot memory size                                       |
+  |           |<------------- Reserved dump area ----------- -->|
+  V           V                                                 V
+  +-----------+----------/ /---+---+----+-----------+----+------+
+  |           |                |CPU|HPTE|  DUMP     |ELF |      |
+  +-----------+----------/ /---+---+----+-----------+----+------+
+        |                                              |
+        V                                              V
+   Used by second                                /proc/vmcore
+   kernel to boot
+                   Fig. 2
+
+Currently the dump will be copied from /proc/vmcore to a
+a new file upon user intervention. The dump data available through
+/proc/vmcore will be in ELF format. Hence the existing kdump
+infrastructure (kdump scripts) to save the dump works fine with
+minor modifications.
+
+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.
+   By default, fadump reserved memory will be initialized as CMA area.
+   Alternatively, user can boot linux kernel with 'fadump=nocma' to
+   prevent fadump to use CMA.
+3. Optionally, user can also set 'crashkernel=' kernel cmdline
+   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.
+
+Sysfs/debugfs files:
+--------------------
+
+Firmware-assisted dump feature uses sysfs file system to hold
+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
+
+    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.
+
+    To register fadump echo 1 > /sys/kernel/fadump_registered and
+    echo 0 > /sys/kernel/fadump_registered for un-register and stop the
+    fadump. Once the fadump is un-registered, the system crash will not
+    be handled and vmcore will not be captured. This interface can be
+    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::
+
+       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.
+
+    The existing userspace tools (kdump infrastructure) can be easily
+    enhanced to use this interface to release the memory reserved for
+    dump and continue without 2nd reboot.
+
+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>
+
+    e.g.
+    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
+
+    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
+
+NOTE:
+      Please refer to Documentation/filesystems/debugfs.txt on
+      how to mount the debugfs filesystem.
+
+
+TODO:
+-----
+ - 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.
+ - 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
+   correct data before it gets exported through /proc/vmcore. The current
+   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
+       version of the structure.
+       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/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt
deleted file mode 100644 (file)
index 10e7f4d..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-
-                   Firmware-Assisted Dump
-                   ------------------------
-                       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
-to minimize the total elapsed time until the system is back
-in production use.
-
-- Firmware assisted dump (fadump) infrastructure is intended to replace
-  the existing phyp assisted dump.
-- Fadump uses the same firmware interfaces and memory reservation model
-  as phyp assisted dump.
-- Unlike phyp dump, fadump exports the memory dump through /proc/vmcore
-  in the ELF format in the same way as kdump. This helps us reuse the
-  kdump infrastructure for dump capture and filtering.
-- Unlike phyp dump, userspace tool does not need to refer any sysfs
-  interface while reading /proc/vmcore.
-- Unlike phyp dump, fadump allows user to release all the memory reserved
-  for dump, with a single operation of echo 1 > /sys/kernel/fadump_release_mem.
-- Once enabled through kernel boot parameter, fadump can be
-  started/stopped through /sys/kernel/fadump_registered interface (see
-  sysfs files section below) and can be easily integrated with kdump
-  service start/stop init scripts.
-
-Comparing with kdump or other strategies, firmware-assisted
-dump offers several strong, practical advantages:
-
--- 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
-   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.
-
-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
-   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
-   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
-         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.
-         Alternatively, user can also specify boot memory size
-         through boot parameter 'crashkernel=' which will override
-         the default calculated size. Use this option if default
-         boot memory size is not sufficient for second kernel to
-         boot successfully. For syntax of crashkernel= parameter,
-         refer to Documentation/admin-guide/kdump/kdump.rst. If any offset is
-         provided in crashkernel= parameter, it will be ignored
-         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
-   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
-   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
-   boot memory size effectively booting with restricted memory
-   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
-   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
-   '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.
-     # echo 1 > /sys/kernel/fadump_release_mem
-
-Please note that the firmware-assisted dump feature
-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
-we check to see if an active dump is waiting for us. If yes
-then everything but boot memory size of RAM is reserved during
-early boot (See Fig. 2). This area is released once we finish
-collecting the dump from user land scripts (e.g. kdump scripts)
-that are run. If there is dump data, then the
-/sys/kernel/fadump_release_mem file is created, and the reserved
-memory is held.
-
-If there is no waiting dump data, then only the memory required
-to hold CPU state, HPTE region, boot memory dump and elfcore
-header, is usually reserved at an offset greater than boot memory
-size (see Fig. 1). This area is *not* released: this region will
-be kept permanently reserved, so that it can act as a receptacle
-for a copy of the boot memory content in addition to CPU state
-and HPTE region, in the case a crash does occur. Since this reserved
-memory area is used only after the system crash, there is no point in
-blocking this significant chunk of memory from production kernel.
-Hence, the implementation uses the Linux kernel's Contiguous Memory
-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.
-
-  o Memory Reservation during first kernel
-
-  Low memory                                         Top of memory
-  0      boot memory size                                       |
-  |           |                |<--Reserved dump area -->|      |
-  V           V                |   Permanent Reservation |      V
-  +-----------+----------/ /---+---+----+-----------+----+------+
-  |           |                |CPU|HPTE|  DUMP     |ELF |      |
-  +-----------+----------/ /---+---+----+-----------+----+------+
-        |                                           ^
-        |                                           |
-        \                                           /
-         -------------------------------------------
-          Boot memory content gets transferred to
-          reserved area by firmware at the time of
-          crash
-                   Fig. 1
-
-  o Memory Reservation during second kernel after crash
-
-  Low memory                                        Top of memory
-  0      boot memory size                                       |
-  |           |<------------- Reserved dump area ----------- -->|
-  V           V                                                 V
-  +-----------+----------/ /---+---+----+-----------+----+------+
-  |           |                |CPU|HPTE|  DUMP     |ELF |      |
-  +-----------+----------/ /---+---+----+-----------+----+------+
-        |                                              |
-        V                                              V
-   Used by second                                /proc/vmcore
-   kernel to boot
-                   Fig. 2
-
-Currently the dump will be copied from /proc/vmcore to a
-a new file upon user intervention. The dump data available through
-/proc/vmcore will be in ELF format. Hence the existing kdump
-infrastructure (kdump scripts) to save the dump works fine with
-minor modifications.
-
-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.
-   By default, fadump reserved memory will be initialized as CMA area.
-   Alternatively, user can boot linux kernel with 'fadump=nocma' to
-   prevent fadump to use CMA.
-3. Optionally, user can also set 'crashkernel=' kernel cmdline
-   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.
-
-Sysfs/debugfs files:
-------------
-
-Firmware-assisted dump feature uses sysfs file system to hold
-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
-
-    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.
-
-    To register fadump echo 1 > /sys/kernel/fadump_registered and
-    echo 0 > /sys/kernel/fadump_registered for un-register and stop the
-    fadump. Once the fadump is un-registered, the system crash will not
-    be handled and vmcore will not be captured. This interface can be
-    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:
-
-    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.
-
-    The existing userspace tools (kdump infrastructure) can be easily
-    enhanced to use this interface to release the memory reserved for
-    dump and continue without 2nd reboot.
-
-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>
-
-    e.g.
-    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
-
-    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
-
-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
-   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
-   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
-   correct data before it gets exported through /proc/vmcore. The current
-   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
-       version of the structure.
-       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.rst b/Documentation/powerpc/hvcs.rst
new file mode 100644 (file)
index 0000000..6808acd
--- /dev/null
@@ -0,0 +1,581 @@
+===============================================================
+HVCS IBM "Hypervisor Virtual Console Server" Installation Guide
+===============================================================
+
+for Linux Kernel 2.6.4+
+
+Copyright (C) 2004 IBM Corporation
+
+.. ===========================================================================
+.. 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
+       3.  Build Options:
+               3.1  Built-in:
+               3.2  Module:
+       4.  Installation:
+       5.  Connection:
+       6.  Disconnection:
+       7.  Configuration:
+       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
+space applications access to the system consoles of logically partitioned
+operating systems (Linux and AIX) running on the same partitioned Power5
+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.
+
+This driver was written to operate solely on IBM Power5 ppc64 hardware
+though some care was taken to abstract the architecture dependent firmware
+calls from the driver code.
+
+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
+requested by the registering driver.  The hvcs driver asks the tty layer
+for 64 of these major/minor numbers by default to use for hvcs device node
+entries.
+
+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::
+
+       Device Drivers  --->
+               Character devices  --->
+                       <*> IBM Hypervisor Virtual Console Server Support
+
+Begin the kernel make process.
+
+3.2 Module:
+-----------
+
+The following menuconfig example demonstrates selecting to build this
+driver as a kernel module::
+
+       Device Drivers  --->
+               Character devices  --->
+                       <M> IBM Hypervisor Virtual Console Server Support
+
+The make process will build the following kernel modules:
+
+       - hvcs.ko
+       - hvcserver.ko
+
+To insert the module with the default allocation execute the following
+commands in the order they appear::
+
+       insmod hvcserver.ko
+       insmod hvcs.ko
+
+The hvcserver module contains architecture specific firmware calls and must
+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)::
+
+       insmod hvcs.ko hvcs_parm_num_devs=4
+
+There is a maximum number of dev entries that can be specified on insmod.
+We think that 1024 is currently a decent maximum number of server adapters
+to allow.  This can always be changed by modifying the constant in the
+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::
+
+       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::
+
+       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::
+
+       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::
+
+       sys/
+       |-- *other sysfs base dirs*
+       |
+       |-- class
+       |   |-- *other classes of devices*
+       |   |
+       |   `-- tty
+       |       |-- *other tty devices*
+       |       |
+       |       |-- hvcs0
+       |       |   `-- dev
+       |       |-- hvcs1
+       |       |   `-- dev
+       |       |-- hvcs2
+       |       |   `-- dev
+       |       |-- hvcs3
+       |       |   `-- dev
+       |       |
+       |       |-- *other tty devices*
+       |
+       |-- *other sysfs base dirs*
+
+For the above examples the following output is a result of cat'ing the
+"dev" entry in the hvcs directory::
+
+       Pow5:/sys/class/tty/hvcs0/ # cat dev
+       254:0
+
+       Pow5:/sys/class/tty/hvcs1/ # cat dev
+       254:1
+
+       Pow5:/sys/class/tty/hvcs2/ # cat dev
+       254:2
+
+       Pow5:/sys/class/tty/hvcs3/ # cat dev
+       254:3
+
+The output from reading the "dev" attribute is the char device major and
+minor numbers that the tty layer has allocated for this driver's use.  Most
+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 /dev/hvcs0 c 254 0
+       mknod /dev/hvcs1 c 254 1
+       mknod /dev/hvcs2 c 254 2
+       mknod /dev/hvcs3 c 254 3
+
+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::
+
+       "/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
+method (e.g. "cat", "dd", "echo").  The intent of this driver however, is
+to provide real time console interaction with a Linux partition's console,
+which requires the use of applications that provide bi-directional,
+interactive I/O with a tty device.
+
+Applications (e.g. "minicom" and "screen") that act as terminal emulators
+or perform terminal type control sequence conversion on the data being
+passed through them are NOT acceptable for providing interactive console
+I/O.  These programs often emulate antiquated terminal types (vt100 and
+ANSI) and expect inbound data to take the form of one of these supported
+terminal types but they either do not convert, or do not _adequately_
+convert, outbound data into the terminal type of the terminal which invoked
+them (though screen makes an attempt and can apparently be configured with
+much termcap wrestling.)
+
+For this reason kermit and cu are two of the recommended applications for
+interacting with a Linux console via an hvcs device.  These programs simply
+act as a conduit for data transfer to and from the tty device.  They do not
+require inbound data to take the form of a particular terminal type, nor do
+they cook outbound data to a particular terminal type.
+
+In order to ensure proper functioning of console applications one must make
+sure that once connected to a /dev/hvcs console that the console's $TERM
+env variable is set to the exact terminal type of the terminal emulator
+used to launch the interactive I/O application.  If one is using xterm and
+kermit to connect to /dev/hvcs0 when the console prompt becomes available
+one should "export TERM=xterm" on the console.  This tells ncurses
+applications that are invoked from the console that they should output
+control sequences that xterm can understand.
+
+As a precautionary measure an hvcs user should always "exit" from their
+session before disconnecting an application such as kermit from the device
+node.  If this is not done, the next user to connect to the console will
+continue using the previous user's logged in session which includes
+using the $TERM variable that the previous user supplied.
+
+Hotplug add and remove of vty-server adapters affects which /dev/hvcs* node
+is used to connect to each vty-server adapter.  In order to determine which
+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::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
+       2
+
+This index of '2' means that in order to connect to vty-server adapter
+30000004 the user should interact with /dev/hvcs2.
+
+It should be noted that due to the system hotplug I/O capabilities of a
+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
+and discards that data when a connection between a vty-server and a vty has
+been severed.  As an example, when a vty-server is immediately disconnected
+from a vty following output of data to the vty the vty adapter may not have
+enough time between when it received the data interrupt and when the
+connection was severed to fetch the data from firmware before the fetch is
+disabled by firmware.
+
+When hvcs is being used to serve consoles this behavior is not a huge issue
+because the adapter stays connected for large amounts of time following
+almost all data writes.  When hvcs is being used as a tty conduit to tunnel
+data between two partitions [see Q & A below] this is a huge problem
+because the standard Linux behavior when cat'ing or dd'ing data to a device
+is to open the tty, send the data, and then close the tty.  If this driver
+manually terminated vty-server connections on tty close this would close
+the vty-server and vty connection before the target vty has had a chance to
+fetch the data.
+
+Additionally, disconnecting a vty-server and vty only on module removal or
+adapter removal is impractical because other vty-servers in other
+partitions may require the usage of the target vty at any time.
+
+Due to this behavioral restriction disconnection of vty-servers from the
+connected vty is a manual procedure using a write to a sysfs attribute
+outlined below, on the other hand the initial vty-server connection to a
+vty is established automatically by this driver.  Manual vty-server
+connection is never required.
+
+In order to terminate the connection between a vty-server and vty the
+"vterm_state" sysfs attribute within each vty-server's sysfs entry is used.
+Reading this attribute reveals the current connection state of the
+vty-server adapter.  A zero means that the vty-server is not connected to a
+vty.  A one indicates that a connection is active.
+
+Writing a '0' (zero) to the vterm_state attribute will disconnect the VTERM
+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::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
+       1
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo 0 > vterm_state
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
+       0
+
+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::
+
+       Pow5:/sys/bus/vio/drivers/hvcs # ls
+       .  ..  30000003  30000004  rescan
+
+By design, firmware notifies the hvcs driver of vty-server lifetimes and
+partner vty removals but not the addition of partner vtys.  Since an HMC
+Super Admin can add partner info dynamically we have provided the hvcs
+driver sysfs directory with the "rescan" update attribute which will query
+firmware and update the partner info for all the vty-servers that this
+driver manages.  Writing a '1' to the attribute triggers the update.  An
+explicit example follows:
+
+       Pow5:/sys/bus/vio/drivers/hvcs # echo 1 > rescan
+
+Reading the attribute will indicate a state of '1' or '0'.  A one indicates
+that an update is in process.  A zero indicates that an update has
+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::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
+       .   current_vty   devspec       name          partner_vtys
+       ..  index         partner_clcs  vterm_state
+
+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::
+
+       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::
+
+       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"::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_vtys
+       30000000
+       30000001
+       30000002
+       30000000
+       30000000
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_clcs
+       U5112.428.103048A-V3-C0
+       U5112.428.103048A-V3-C2
+       U5112.428.103048A-V3-C3
+       U5112.428.103048A-V4-C0
+       U5112.428.103048A-V5-C0
+
+Reading partner_vtys returns a list of partner vtys.  Vty unit address
+numbering is only per-partition-unique so entries will frequently repeat.
+
+Reading partner_clcs returns a list of "converged location codes" which are
+composed of a system serial number followed by "-V*", where the '*' is the
+target partition number, and "-C*", where the '*' is the slot of the
+adapter.  The first vty partner corresponds to the first clc item, the
+second vty partner to the second clc item, etc.
+
+A vty-server can only be connected to a single vty at a time.  The entry,
+"current_vty" prints the clc of the currently selected partner vty when
+read.
+
+The current_vty can be changed by writing a valid partner clc to the entry
+as in the following example::
+
+       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo U5112.428.10304
+       8A-V4-C0 > current_vty
+
+Changing the current_vty when a vty-server is already connected to a vty
+does not affect the current connection.  The change takes effect when the
+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:
+
+       1. The creator of the /dev/hvcs* nodes has the ability to restrict
+       the access of the device entries to certain users or groups.  It
+       may be best to create a special hvcs group privilege for providing
+       access to system consoles.
+
+       2. To provide network security when grabbing the console it is
+       suggested that the user connect to the console hosting partition
+       using a secure method, such as SSH or sit at a hardware console.
+
+       3. Make sure to exit the user session when done with a console or
+       the next vty-server connection (which may be from another
+       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:
+
+A: You can use "screen" to directly connect to the /dev/hvcs* device and
+setup a session on your machine with the console group privileges.  As
+pointed out earlier by default screen doesn't provide the termcap settings
+for most terminal emulators to provide adequate character conversion from
+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?
+
+A: Please see the preceding section on "Connection" for a discussion of how
+applications can affect the display of character control sequences.
+Additionally, just because you logged into the console using and xterm
+doesn't mean someone else didn't log into the console with the HMC console
+(vt320) before you and leave the session logged in.  The best thing to do
+is to export TERM to the terminal type of your terminal emulator when you
+get the console.  Additionally make sure to "exit" the console before you
+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?
+
+A: Some other Power5 console mechanism has a connection to the vty and
+isn't giving it up.  You can try to force disconnect the consoles from the
+HMC by right clicking on the partition and then selecting "close terminal".
+Otherwise you have to hunt down the people who have console authority.  It
+is possible that you already have the console open using another kermit
+session and just forgot about it.  Please review the console options for
+Power5 systems to determine the many ways a system console can be held.
+
+OR
+
+A: Another user may not have a connectivity method currently attached to a
+/dev/hvcs device but the vterm_state may reveal that they still have the
+vty-server connection established.  They need to free this using the method
+outlined in the section on "Disconnection" in order for others to connect
+to the target vty.
+
+OR
+
+A: The user profile you are using to execute kermit probably doesn't have
+permissions to use the /dev/hvcs* device.
+
+OR
+
+A: You probably haven't inserted the hvcs.ko module yet but the /dev/hvcs*
+entry still exists (on systems without udev).
+
+OR
+
+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."
+
+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?
+
+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?
+
+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
+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?
+
+A: Assignment of vty-server adapters to /dev/hvcs* entries is always done
+in the order that the adapters are exposed.  Due to hotplug capabilities of
+this driver assignment of hotplug added vty-servers may be in a different
+order than how they would be exposed on module load.  Rebooting or
+reloading the module after dynamic addition may result in the /dev/hvcs*
+and vty-server coupling changing if a vty-server adapter was added in a
+slot between two other vty-server adapters.  Refer to the section above
+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?
+
+A: Yes, on Power5 platforms the hvc_console driver provides a tty interface
+for extra /dev/hvc* devices (where /dev/hvc0 is most likely the console).
+In order to get a tty conduit working between the two partitions the HMC
+Super Admin must create an additional "serial server" for the target
+partition with the HMC gui which will show up as /dev/hvc* when the target
+partition is rebooted.
+
+The HMC Super Admin then creates an additional "serial client" for the
+current partition and points this at the target partition's newly created
+"serial server" adapter (remember the slot).  This shows up as an
+additional /dev/hvcs* device.
+
+Now a program on the target system can be configured to read or write to
+/dev/hvc* and another program on the current partition can be configured to
+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
+PowerPC development mailing list at:
+
+linuxppc-dev@lists.ozlabs.org
+
+This request is to provide a documented and searchable public exchange
+of the problems and solutions surrounding this driver for the benefit of
+all users.
diff --git a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt
deleted file mode 100644 (file)
index a730ca5..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-===========================================================================
-                                  HVCS
-       IBM "Hypervisor Virtual Console Server" Installation Guide
-                         for Linux Kernel 2.6.4+
-                   Copyright (C) 2004 IBM Corporation
-
-===========================================================================
-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
-       3.  Build Options:
-               3.1  Built-in:
-               3.2  Module:
-       4.  Installation:
-       5.  Connection:
-       6.  Disconnection:
-       7.  Configuration:
-       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
-space applications access to the system consoles of logically partitioned
-operating systems (Linux and AIX) running on the same partitioned Power5
-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.
-
-This driver was written to operate solely on IBM Power5 ppc64 hardware
-though some care was taken to abstract the architecture dependent firmware
-calls from the driver code.
-
-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
-requested by the registering driver.  The hvcs driver asks the tty layer
-for 64 of these major/minor numbers by default to use for hvcs device node
-entries.
-
-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.
-
-       Device Drivers  --->
-               Character devices  --->
-                       <*> IBM Hypervisor Virtual Console Server Support
-
-Begin the kernel make process.
-
----------------------------------------------------------------------------
-3.2 Module:
-
-The following menuconfig example demonstrates selecting to build this
-driver as a kernel module.
-
-       Device Drivers  --->
-               Character devices  --->
-                       <M> IBM Hypervisor Virtual Console Server Support
-
-The make process will build the following kernel modules:
-
-       hvcs.ko
-       hvcserver.ko
-
-To insert the module with the default allocation execute the following
-commands in the order they appear:
-
-       insmod hvcserver.ko
-       insmod hvcs.ko
-
-The hvcserver module contains architecture specific firmware calls and must
-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):
-
-       insmod hvcs.ko hvcs_parm_num_devs=4
-
-There is a maximum number of dev entries that can be specified on insmod.
-We think that 1024 is currently a decent maximum number of server adapters
-to allow.  This can always be changed by modifying the constant in the
-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:
-
-       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:
-
-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:
-
-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:
-
-       sys/
-       |-- *other sysfs base dirs*
-       |
-       |-- class
-       |   |-- *other classes of devices*
-       |   |
-       |   `-- tty
-       |       |-- *other tty devices*
-       |       |
-       |       |-- hvcs0
-       |       |   `-- dev
-       |       |-- hvcs1
-       |       |   `-- dev
-       |       |-- hvcs2
-       |       |   `-- dev
-       |       |-- hvcs3
-       |       |   `-- dev
-       |       |
-       |       |-- *other tty devices*
-       |
-       |-- *other sysfs base dirs*
-
-For the above examples the following output is a result of cat'ing the
-"dev" entry in the hvcs directory:
-
-       Pow5:/sys/class/tty/hvcs0/ # cat dev
-       254:0
-
-       Pow5:/sys/class/tty/hvcs1/ # cat dev
-       254:1
-
-       Pow5:/sys/class/tty/hvcs2/ # cat dev
-       254:2
-
-       Pow5:/sys/class/tty/hvcs3/ # cat dev
-       254:3
-
-The output from reading the "dev" attribute is the char device major and
-minor numbers that the tty layer has allocated for this driver's use.  Most
-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 /dev/hvcs0 c 254 0
-       mknod /dev/hvcs1 c 254 1
-       mknod /dev/hvcs2 c 254 2
-       mknod /dev/hvcs3 c 254 3
-
-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:
-
-       "/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
-method (e.g. "cat", "dd", "echo").  The intent of this driver however, is
-to provide real time console interaction with a Linux partition's console,
-which requires the use of applications that provide bi-directional,
-interactive I/O with a tty device.
-
-Applications (e.g. "minicom" and "screen") that act as terminal emulators
-or perform terminal type control sequence conversion on the data being
-passed through them are NOT acceptable for providing interactive console
-I/O.  These programs often emulate antiquated terminal types (vt100 and
-ANSI) and expect inbound data to take the form of one of these supported
-terminal types but they either do not convert, or do not _adequately_
-convert, outbound data into the terminal type of the terminal which invoked
-them (though screen makes an attempt and can apparently be configured with
-much termcap wrestling.)
-
-For this reason kermit and cu are two of the recommended applications for
-interacting with a Linux console via an hvcs device.  These programs simply
-act as a conduit for data transfer to and from the tty device.  They do not
-require inbound data to take the form of a particular terminal type, nor do
-they cook outbound data to a particular terminal type.
-
-In order to ensure proper functioning of console applications one must make
-sure that once connected to a /dev/hvcs console that the console's $TERM
-env variable is set to the exact terminal type of the terminal emulator
-used to launch the interactive I/O application.  If one is using xterm and
-kermit to connect to /dev/hvcs0 when the console prompt becomes available
-one should "export TERM=xterm" on the console.  This tells ncurses
-applications that are invoked from the console that they should output
-control sequences that xterm can understand.
-
-As a precautionary measure an hvcs user should always "exit" from their
-session before disconnecting an application such as kermit from the device
-node.  If this is not done, the next user to connect to the console will
-continue using the previous user's logged in session which includes
-using the $TERM variable that the previous user supplied.
-
-Hotplug add and remove of vty-server adapters affects which /dev/hvcs* node
-is used to connect to each vty-server adapter.  In order to determine which
-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.
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
-       2
-
-This index of '2' means that in order to connect to vty-server adapter
-30000004 the user should interact with /dev/hvcs2.
-
-It should be noted that due to the system hotplug I/O capabilities of a
-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
-and discards that data when a connection between a vty-server and a vty has
-been severed.  As an example, when a vty-server is immediately disconnected
-from a vty following output of data to the vty the vty adapter may not have
-enough time between when it received the data interrupt and when the
-connection was severed to fetch the data from firmware before the fetch is
-disabled by firmware.
-
-When hvcs is being used to serve consoles this behavior is not a huge issue
-because the adapter stays connected for large amounts of time following
-almost all data writes.  When hvcs is being used as a tty conduit to tunnel
-data between two partitions [see Q & A below] this is a huge problem
-because the standard Linux behavior when cat'ing or dd'ing data to a device
-is to open the tty, send the data, and then close the tty.  If this driver
-manually terminated vty-server connections on tty close this would close
-the vty-server and vty connection before the target vty has had a chance to
-fetch the data.
-
-Additionally, disconnecting a vty-server and vty only on module removal or
-adapter removal is impractical because other vty-servers in other
-partitions may require the usage of the target vty at any time.
-
-Due to this behavioral restriction disconnection of vty-servers from the
-connected vty is a manual procedure using a write to a sysfs attribute
-outlined below, on the other hand the initial vty-server connection to a
-vty is established automatically by this driver.  Manual vty-server
-connection is never required.
-
-In order to terminate the connection between a vty-server and vty the
-"vterm_state" sysfs attribute within each vty-server's sysfs entry is used.
-Reading this attribute reveals the current connection state of the
-vty-server adapter.  A zero means that the vty-server is not connected to a
-vty.  A one indicates that a connection is active.
-
-Writing a '0' (zero) to the vterm_state attribute will disconnect the VTERM
-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.
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
-       1
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo 0 > vterm_state
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat vterm_state
-       0
-
-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:
-
-       Pow5:/sys/bus/vio/drivers/hvcs # ls
-       .  ..  30000003  30000004  rescan
-
-By design, firmware notifies the hvcs driver of vty-server lifetimes and
-partner vty removals but not the addition of partner vtys.  Since an HMC
-Super Admin can add partner info dynamically we have provided the hvcs
-driver sysfs directory with the "rescan" update attribute which will query
-firmware and update the partner info for all the vty-servers that this
-driver manages.  Writing a '1' to the attribute triggers the update.  An
-explicit example follows:
-
-       Pow5:/sys/bus/vio/drivers/hvcs # echo 1 > rescan
-
-Reading the attribute will indicate a state of '1' or '0'.  A one indicates
-that an update is in process.  A zero indicates that an update has
-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:
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
-       .   current_vty   devspec       name          partner_vtys
-       ..  index         partner_clcs  vterm_state
-
-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:
-
-       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:
-
-       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".
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_vtys
-       30000000
-       30000001
-       30000002
-       30000000
-       30000000
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat partner_clcs
-       U5112.428.103048A-V3-C0
-       U5112.428.103048A-V3-C2
-       U5112.428.103048A-V3-C3
-       U5112.428.103048A-V4-C0
-       U5112.428.103048A-V5-C0
-
-Reading partner_vtys returns a list of partner vtys.  Vty unit address
-numbering is only per-partition-unique so entries will frequently repeat.
-
-Reading partner_clcs returns a list of "converged location codes" which are
-composed of a system serial number followed by "-V*", where the '*' is the
-target partition number, and "-C*", where the '*' is the slot of the
-adapter.  The first vty partner corresponds to the first clc item, the
-second vty partner to the second clc item, etc.
-
-A vty-server can only be connected to a single vty at a time.  The entry,
-"current_vty" prints the clc of the currently selected partner vty when
-read.
-
-The current_vty can be changed by writing a valid partner clc to the entry
-as in the following example:
-
-       Pow5:/sys/bus/vio/drivers/hvcs/30000004 # echo U5112.428.10304
-       8A-V4-C0 > current_vty
-
-Changing the current_vty when a vty-server is already connected to a vty
-does not affect the current connection.  The change takes effect when the
-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:
-
-       1. The creator of the /dev/hvcs* nodes has the ability to restrict
-       the access of the device entries to certain users or groups.  It
-       may be best to create a special hvcs group privilege for providing
-       access to system consoles.
-
-       2. To provide network security when grabbing the console it is
-       suggested that the user connect to the console hosting partition
-       using a secure method, such as SSH or sit at a hardware console.
-
-       3. Make sure to exit the user session when done with a console or
-       the next vty-server connection (which may be from another
-       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:
-
-A: You can use "screen" to directly connect to the /dev/hvcs* device and
-setup a session on your machine with the console group privileges.  As
-pointed out earlier by default screen doesn't provide the termcap settings
-for most terminal emulators to provide adequate character conversion from
-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?
-
-A: Please see the preceding section on "Connection" for a discussion of how
-applications can affect the display of character control sequences.
-Additionally, just because you logged into the console using and xterm
-doesn't mean someone else didn't log into the console with the HMC console
-(vt320) before you and leave the session logged in.  The best thing to do
-is to export TERM to the terminal type of your terminal emulator when you
-get the console.  Additionally make sure to "exit" the console before you
-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?
-
-A: Some other Power5 console mechanism has a connection to the vty and
-isn't giving it up.  You can try to force disconnect the consoles from the
-HMC by right clicking on the partition and then selecting "close terminal".
-Otherwise you have to hunt down the people who have console authority.  It
-is possible that you already have the console open using another kermit
-session and just forgot about it.  Please review the console options for
-Power5 systems to determine the many ways a system console can be held.
-
-OR
-
-A: Another user may not have a connectivity method currently attached to a
-/dev/hvcs device but the vterm_state may reveal that they still have the
-vty-server connection established.  They need to free this using the method
-outlined in the section on "Disconnection" in order for others to connect
-to the target vty.
-
-OR
-
-A: The user profile you are using to execute kermit probably doesn't have
-permissions to use the /dev/hvcs* device.
-
-OR
-
-A: You probably haven't inserted the hvcs.ko module yet but the /dev/hvcs*
-entry still exists (on systems without udev).
-
-OR
-
-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."
-
-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?
-
-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?
-
-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
-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?
-
-A: Assignment of vty-server adapters to /dev/hvcs* entries is always done
-in the order that the adapters are exposed.  Due to hotplug capabilities of
-this driver assignment of hotplug added vty-servers may be in a different
-order than how they would be exposed on module load.  Rebooting or
-reloading the module after dynamic addition may result in the /dev/hvcs*
-and vty-server coupling changing if a vty-server adapter was added in a
-slot between two other vty-server adapters.  Refer to the section above
-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?
-
-A: Yes, on Power5 platforms the hvc_console driver provides a tty interface
-for extra /dev/hvc* devices (where /dev/hvc0 is most likely the console).
-In order to get a tty conduit working between the two partitions the HMC
-Super Admin must create an additional "serial server" for the target
-partition with the HMC gui which will show up as /dev/hvc* when the target
-partition is rebooted.
-
-The HMC Super Admin then creates an additional "serial client" for the
-current partition and points this at the target partition's newly created
-"serial server" adapter (remember the slot).  This shows up as an
-additional /dev/hvcs* device.
-
-Now a program on the target system can be configured to read or write to
-/dev/hvc* and another program on the current partition can be configured to
-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
-PowerPC development mailing list at:
-
-linuxppc-dev@lists.ozlabs.org
-
-This request is to provide a documented and searchable public exchange
-of the problems and solutions surrounding this driver for the benefit of
-all users.
diff --git a/Documentation/powerpc/index.rst b/Documentation/powerpc/index.rst
new file mode 100644 (file)
index 0000000..549b1cd
--- /dev/null
@@ -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`
index 66c2414..a363d8c 100644 (file)
@@ -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.rst b/Documentation/powerpc/mpc52xx.rst
new file mode 100644 (file)
index 0000000..8676ac6
--- /dev/null
@@ -0,0 +1,43 @@
+=============================
+Linux 2.6.x on MPC52xx family
+=============================
+
+For the latest info, go to http://www.246tNt.com/mpc52xx/
+
+To compile/use :
+
+  - U-Boot::
+
+     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
+        if you wish to ).
+     # make lite5200_defconfig
+     # make uImage
+
+     then, on U-boot:
+     => tftpboot 200000 uImage
+     => tftpboot 400000 pRamdisk
+     => bootm 200000 400000
+
+  - DBug::
+
+     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
+        if you wish to ).
+     # make lite5200_defconfig
+     # cp your_initrd.gz arch/ppc/boot/images/ramdisk.image.gz
+     # make zImage.initrd
+     # make
+
+     then in DBug:
+     DBug> dn -i zImage.initrd.lite5200
+
+
+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
+   nothing to do with the MPC5200. I also included the 'MPC' for the same
+   reason.
+ - Of course, I inspired myself from the 2.4 port. If you think I forgot to
+   mention you/your company in the copyright of some code, I'll correct it
+   ASAP.
diff --git a/Documentation/powerpc/mpc52xx.txt b/Documentation/powerpc/mpc52xx.txt
deleted file mode 100644 (file)
index 0d540a3..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-Linux 2.6.x on MPC52xx family
------------------------------
-
-For the latest info, go to http://www.246tNt.com/mpc52xx/
-
-To compile/use :
-
-  - U-Boot:
-     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
-        if you wish to ).
-     # make lite5200_defconfig
-     # make uImage
-
-     then, on U-boot:
-     => tftpboot 200000 uImage
-     => tftpboot 400000 pRamdisk
-     => bootm 200000 400000
-
-  - DBug:
-     # <edit Makefile to set ARCH=ppc & CROSS_COMPILE=... ( also EXTRAVERSION
-        if you wish to ).
-     # make lite5200_defconfig
-     # cp your_initrd.gz arch/ppc/boot/images/ramdisk.image.gz
-     # make zImage.initrd
-     # make
-
-     then in DBug:
-     DBug> dn -i zImage.initrd.lite5200
-
-
-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
-   nothing to do with the MPC5200. I also included the 'MPC' for the same
-   reason.
- - Of course, I inspired myself from the 2.4 port. If you think I forgot to
-   mention you/your company in the copyright of some code, I'll correct it
-   ASAP.
diff --git a/Documentation/powerpc/pci_iov_resource_on_powernv.rst b/Documentation/powerpc/pci_iov_resource_on_powernv.rst
new file mode 100644 (file)
index 0000000..f5a5793
--- /dev/null
@@ -0,0 +1,312 @@
+===================================================
+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
+sizing and assignment on PowerKVM and how generic PCI code handles this
+requirement. The first two sections describe the concepts of Partitionable
+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
+partitions (i.e., filtering of DMA, MSIs etc.) and to provide a mechanism
+to freeze a device that is causing errors in order to limit the possibility
+of propagation of bad data.
+
+There is thus, in HW, a table of PE states that contains a pair of "frozen"
+state bits (one for MMIO and one for DMA, they get set together but can be
+cleared independently) for each PE.
+
+When a PE is frozen, all stores in any direction are dropped and all loads
+return all 1's value. MSIs are also blocked. There's a bit more state that
+captures things like the details of the error that caused the freeze etc., but
+that's not critical.
+
+The interesting part is how the various PCIe transactions (MMIO, DMA, ...)
+are matched to their corresponding PEs.
+
+The following section provides a rough description of what we have on P8
+(IODA2).  Keep in mind that this is all per PHB (PCI host bridge).  Each PHB
+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.
+
+  * Inbound
+
+    For DMA, MSIs and inbound PCIe error messages, we have a table (in
+    memory but accessed in HW by the chip) that provides a direct
+    correspondence between a PCIe RID (bus/dev/fn) with a PE number.
+    We call this the RTT.
+
+    - For DMA we then provide an entire address space for each PE that can
+      contain two "windows", depending on the value of PCI address bit 59.
+      Each window can be configured to be remapped via a "TCE table" (IOMMU
+      translation table), which has various configurable characteristics
+      not described here.
+
+    - For MSIs, we have two windows in the address space (one at the top of
+      the 32-bit space and one much higher) which, via a combination of the
+      address and MSI value, will result in one of the 2048 interrupts per
+      bridge being triggered.  There's a PE# in the interrupt controller
+      descriptor table as well which is compared with the PE# obtained from
+      the RTT to "authorize" the device to emit that specific interrupt.
+
+    - Error messages just use the RTT.
+
+  * Outbound.  That's where the tricky part is.
+
+    Like other PCI host bridges, the Power8 IODA2 PHB supports "windows"
+    from the CPU address space to the PCI address space.  There is one M32
+    window and sixteen M64 windows.  They have different characteristics.
+    First what they have in common: they forward a configurable portion of
+    the CPU address space to the PCIe bus and must be naturally aligned
+    power of two in size.  The rest is different:
+
+    - The M32 window:
+
+      * Is limited to 4GB in size.
+
+      * Drops the top bits of the address (above the size) and replaces
+       them with a configurable value.  This is typically used to generate
+       32-bit PCIe accesses.  We configure that window at boot from FW and
+       don't touch it from Linux; it's usually set to forward a 2GB
+       portion of address space from the CPU to PCIe
+       0x8000_0000..0xffff_ffff.  (Note: The top 64KB are actually
+       reserved for MSIs but this is not a problem at this point; we just
+       need to ensure Linux doesn't assign anything there, the M32 logic
+       ignores that however and will forward in that space if we try).
+
+      * It is divided into 256 segments of equal size.  A table in the chip
+       maps each segment to a PE#.  That allows portions of the MMIO space
+       to be assigned to PEs on a segment granularity.  For a 2GB window,
+       the segment granularity is 2GB/256 = 8MB.
+
+    Now, this is the "main" window we use in Linux today (excluding
+    SR-IOV).  We basically use the trick of forcing the bridge MMIO windows
+    onto a segment alignment/granularity so that the space behind a bridge
+    can be assigned to a PE.
+
+    Ideally we would like to be able to have individual functions in PEs
+    but that would mean using a completely different address allocation
+    scheme where individual function BARs can be "grouped" to fit in one or
+    more segments.
+
+    - The M64 windows:
+
+      * Must be at least 256MB in size.
+
+      * Do not translate addresses (the address on PCIe is the same as the
+       address on the PowerBus).  There is a way to also set the top 14
+       bits which are not conveyed by PowerBus but we don't use this.
+
+      * Can be configured to be segmented.  When not segmented, we can
+       specify the PE# for the entire window.  When segmented, a window
+       has 256 segments; however, there is no table for mapping a segment
+       to a PE#.  The segment number *is* the PE#.
+
+      * Support overlaps.  If an address is covered by multiple windows,
+       there's a defined ordering for which window applies.
+
+    We have code (fairly new compared to the M32 stuff) that exploits that
+    for large BARs in 64-bit space:
+
+    We configure an M64 window to cover the entire region of address space
+    that has been assigned by FW for the PHB (about 64GB, ignore the space
+    for the M32, it comes out of a different "reserve").  We configure it
+    as segmented.
+
+    Then we do the same thing as with M32, using the bridge alignment
+    trick, to match to those giant segments.
+
+    Since we cannot remap, we have two additional constraints:
+
+    - We do the PE# allocation *after* the 64-bit space has been assigned
+      because the addresses we use directly determine the PE#.  We then
+      update the M32 PE# for the devices that use both 32-bit and 64-bit
+      spaces or assign the remaining PE# to 32-bit only devices.
+
+    - We cannot "group" segments in HW, so if a device ends up using more
+      than one segment, we end up with more than one PE#.  There is a HW
+      mechanism to make the freeze state cascade to "companion" PEs but
+      that only works for PCIe error messages (typically used so that if
+      you freeze a switch, it freezes all its children).  So we do it in
+      SW.  We lose a bit of effectiveness of EEH in that case, but that's
+      the best we found.  So when any of the PEs freezes, we freeze the
+      other ones for that "domain".  We thus introduce the concept of
+      "master PE" which is the one used for DMA, MSIs, etc., and "secondary
+      PEs" that are used for the remaining M64 segments.
+
+    We would like to investigate using additional M64 windows in "single
+    PE" mode to overlay over specific BARs to work around some of that, for
+    example for devices with very large BARs, e.g., GPUs.  It would make
+    sense, but we haven't done it yet.
+
+3. Considerations for SR-IOV on PowerKVM
+========================================
+
+  * SR-IOV Background
+
+    The PCIe SR-IOV feature allows a single Physical Function (PF) to
+    support several Virtual Functions (VFs).  Registers in the PF's SR-IOV
+    Capability control the number of VFs and whether they are enabled.
+
+    When VFs are enabled, they appear in Configuration Space like normal
+    PCI devices, but the BARs in VF config space headers are unusual.  For
+    a non-VF device, software uses BARs in the config space header to
+    discover the BAR sizes and assign addresses for them.  For VF devices,
+    software uses VF BAR registers in the *PF* SR-IOV Capability to
+    discover sizes and assign addresses.  The BARs in the VF's config space
+    header are read-only zeros.
+
+    When a VF BAR in the PF SR-IOV Capability is programmed, it sets the
+    base address for all the corresponding VF(n) BARs.  For example, if the
+    PF SR-IOV Capability is programmed to enable eight VFs, and it has a
+    1MB VF BAR0, the address in that VF BAR sets the base of an 8MB region.
+    This region is divided into eight contiguous 1MB regions, each of which
+    is a BAR0 for one of the VFs.  Note that even though the VF BAR
+    describes an 8MB region, the alignment requirement is for a single VF,
+    i.e., 1MB in this example.
+
+  There are several strategies for isolating VFs in PEs:
+
+  - M32 window: There's one M32 window, and it is split into 256
+    equally-sized segments.  The finest granularity possible is a 256MB
+    window with 1MB segments.  VF BARs that are 1MB or larger could be
+    mapped to separate PEs in this window.  Each segment can be
+    individually mapped to a PE via the lookup table, so this is quite
+    flexible, but it works best when all the VF BARs are the same size.  If
+    they are different sizes, the entire window has to be small enough that
+    the segment size matches the smallest VF BAR, which means larger VF
+    BARs span several segments.
+
+  - Non-segmented M64 window: A non-segmented M64 window is mapped entirely
+    to a single PE, so it could only isolate one VF.
+
+  - Single segmented M64 windows: A segmented M64 window could be used just
+    like the M32 window, but the segments can't be individually mapped to
+    PEs (the segment number is the PE#), so there isn't as much
+    flexibility.  A VF with multiple BARs would have to be in a "domain" of
+    multiple PEs, which is not as well isolated as a single PE.
+
+  - Multiple segmented M64 windows: As usual, each window is split into 256
+    equally-sized segments, and the segment number is the PE#.  But if we
+    use several M64 windows, they can be set to different base addresses
+    and different segment sizes.  If we have VFs that each have a 1MB BAR
+    and a 32MB BAR, we could use one M64 window to assign 1MB segments and
+    another M64 window to assign 32MB segments.
+
+  Finally, the plan to use M64 windows for SR-IOV, which will be described
+  more in the next two sections.  For a given VF BAR, we need to
+  effectively reserve the entire 256 segments (256 * VF BAR size) and
+  position the VF BAR to start at the beginning of a free range of
+  segments/PEs inside that M64 window.
+
+  The goal is of course to be able to give a separate PE for each VF.
+
+  The IODA2 platform has 16 M64 windows, which are used to map MMIO
+  range to PE#.  Each M64 window defines one MMIO range and this range is
+  divided into 256 segments, with each segment corresponding to one PE.
+
+  We decide to leverage this M64 window to map VFs to individual PEs, since
+  SR-IOV VF BARs are all the same size.
+
+  But doing so introduces another problem: total_VFs is usually smaller
+  than the number of M64 window segments, so if we map one VF BAR directly
+  to one M64 window, some part of the M64 window will map to another
+  device's MMIO range.
+
+  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::
+
+     0      1                     total_VFs - 1
+     +------+------+-     -+------+------+
+     |      |      |  ...  |      |      |
+     +------+------+-     -+------+------+
+
+                           VF(n) BAR space
+
+     0      1                     total_VFs - 1                255
+     +------+------+-     -+------+------+-      -+------+------+
+     |      |      |  ...  |      |      |   ...  |      |      |
+     +------+------+-     -+------+------+-      -+------+------+
+
+                           M64 window
+
+               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::
+
+     0      1                     total_VFs - 1                255
+     +------+------+-     -+------+------+-      -+------+------+
+     |      |      |  ...  |      |      |   ...  |      |      |
+     +------+------+-     -+------+------+-      -+------+------+
+
+                           VF(n) BAR space + extra
+
+     0      1                     total_VFs - 1                255
+     +------+------+-     -+------+------+-      -+------+------+
+     |      |      |  ...  |      |      |   ...  |      |      |
+     +------+------+-     -+------+------+-      -+------+------+
+
+                          M64 window
+
+               Figure 1.1 Map VF(n) BAR space + extra
+
+  Allocating the extra space ensures that the entire M64 window will be
+  assigned to this one SR-IOV device and none of the space will be
+  available for other devices.  Note that this only expands the space
+  reserved in software; there are still only total_VFs VFs, and they only
+  respond to segments [0, total_VFs - 1].  There's nothing in hardware that
+  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.
+
+In IODA2, the MMIO address determines the PE#.  If the address is in an M32
+window, we can set the PE# by updating the table that translates segments
+to PE#s.  Similarly, if the address is in an unsegmented M64 window, we can
+set the PE# for the window.  But if it's in a segmented M64 window, the
+segment number is the PE#.
+
+Therefore, the only way to control the PE# for a VF is to change the base
+of the VF(n) BAR space in the VF BAR.  If the PCI core allocates the exact
+amount of space required for the VF(n) BAR space, the VF BAR value is fixed
+and cannot be changed.
+
+On the other hand, if the PCI core allocates additional space, the VF BAR
+value can be changed as long as the entire VF(n) BAR space remains inside
+the space allocated by the core.
+
+Ideally the segment size will be the same as an individual VF BAR size.
+Then each VF will be in its own PE.  The VF BARs (and therefore the PE#s)
+are contiguous.  If VF0 is in PE(x), then VF(n) is in PE(x+n).  If we
+allocate 256 segments, there are (256 - numVFs) choices for the PE# of VF0.
+
+If the segment size is smaller than the VF BAR size, it will take several
+segments to cover a VF BAR, and a VF will be in several PEs.  This is
+possible, but the isolation isn't as good, and it reduces the number of PE#
+choices because instead of consuming only numVFs segments, the VF(n) BAR
+space will consume (numVFs * n) segments.  That means there aren't as many
+available segments for adjusting base of the VF(n) BAR space.
diff --git a/Documentation/powerpc/pci_iov_resource_on_powernv.txt b/Documentation/powerpc/pci_iov_resource_on_powernv.txt
deleted file mode 100644 (file)
index b55c5cd..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-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
-sizing and assignment on PowerKVM and how generic PCI code handles this
-requirement. The first two sections describe the concepts of Partitionable
-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
-partitions (i.e., filtering of DMA, MSIs etc.) and to provide a mechanism
-to freeze a device that is causing errors in order to limit the possibility
-of propagation of bad data.
-
-There is thus, in HW, a table of PE states that contains a pair of "frozen"
-state bits (one for MMIO and one for DMA, they get set together but can be
-cleared independently) for each PE.
-
-When a PE is frozen, all stores in any direction are dropped and all loads
-return all 1's value. MSIs are also blocked. There's a bit more state that
-captures things like the details of the error that caused the freeze etc., but
-that's not critical.
-
-The interesting part is how the various PCIe transactions (MMIO, DMA, ...)
-are matched to their corresponding PEs.
-
-The following section provides a rough description of what we have on P8
-(IODA2).  Keep in mind that this is all per PHB (PCI host bridge).  Each PHB
-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.
-
-  * Inbound
-
-    For DMA, MSIs and inbound PCIe error messages, we have a table (in
-    memory but accessed in HW by the chip) that provides a direct
-    correspondence between a PCIe RID (bus/dev/fn) with a PE number.
-    We call this the RTT.
-
-    - For DMA we then provide an entire address space for each PE that can
-      contain two "windows", depending on the value of PCI address bit 59.
-      Each window can be configured to be remapped via a "TCE table" (IOMMU
-      translation table), which has various configurable characteristics
-      not described here.
-
-    - For MSIs, we have two windows in the address space (one at the top of
-      the 32-bit space and one much higher) which, via a combination of the
-      address and MSI value, will result in one of the 2048 interrupts per
-      bridge being triggered.  There's a PE# in the interrupt controller
-      descriptor table as well which is compared with the PE# obtained from
-      the RTT to "authorize" the device to emit that specific interrupt.
-
-    - Error messages just use the RTT.
-
-  * Outbound.  That's where the tricky part is.
-
-    Like other PCI host bridges, the Power8 IODA2 PHB supports "windows"
-    from the CPU address space to the PCI address space.  There is one M32
-    window and sixteen M64 windows.  They have different characteristics.
-    First what they have in common: they forward a configurable portion of
-    the CPU address space to the PCIe bus and must be naturally aligned
-    power of two in size.  The rest is different:
-
-    - The M32 window:
-
-      * Is limited to 4GB in size.
-
-      * Drops the top bits of the address (above the size) and replaces
-       them with a configurable value.  This is typically used to generate
-       32-bit PCIe accesses.  We configure that window at boot from FW and
-       don't touch it from Linux; it's usually set to forward a 2GB
-       portion of address space from the CPU to PCIe
-       0x8000_0000..0xffff_ffff.  (Note: The top 64KB are actually
-       reserved for MSIs but this is not a problem at this point; we just
-       need to ensure Linux doesn't assign anything there, the M32 logic
-       ignores that however and will forward in that space if we try).
-
-      * It is divided into 256 segments of equal size.  A table in the chip
-       maps each segment to a PE#.  That allows portions of the MMIO space
-       to be assigned to PEs on a segment granularity.  For a 2GB window,
-       the segment granularity is 2GB/256 = 8MB.
-
-    Now, this is the "main" window we use in Linux today (excluding
-    SR-IOV).  We basically use the trick of forcing the bridge MMIO windows
-    onto a segment alignment/granularity so that the space behind a bridge
-    can be assigned to a PE.
-
-    Ideally we would like to be able to have individual functions in PEs
-    but that would mean using a completely different address allocation
-    scheme where individual function BARs can be "grouped" to fit in one or
-    more segments.
-
-    - The M64 windows:
-
-      * Must be at least 256MB in size.
-
-      * Do not translate addresses (the address on PCIe is the same as the
-       address on the PowerBus).  There is a way to also set the top 14
-       bits which are not conveyed by PowerBus but we don't use this.
-
-      * Can be configured to be segmented.  When not segmented, we can
-       specify the PE# for the entire window.  When segmented, a window
-       has 256 segments; however, there is no table for mapping a segment
-       to a PE#.  The segment number *is* the PE#.
-
-      * Support overlaps.  If an address is covered by multiple windows,
-       there's a defined ordering for which window applies.
-
-    We have code (fairly new compared to the M32 stuff) that exploits that
-    for large BARs in 64-bit space:
-
-    We configure an M64 window to cover the entire region of address space
-    that has been assigned by FW for the PHB (about 64GB, ignore the space
-    for the M32, it comes out of a different "reserve").  We configure it
-    as segmented.
-
-    Then we do the same thing as with M32, using the bridge alignment
-    trick, to match to those giant segments.
-
-    Since we cannot remap, we have two additional constraints:
-
-    - We do the PE# allocation *after* the 64-bit space has been assigned
-      because the addresses we use directly determine the PE#.  We then
-      update the M32 PE# for the devices that use both 32-bit and 64-bit
-      spaces or assign the remaining PE# to 32-bit only devices.
-
-    - We cannot "group" segments in HW, so if a device ends up using more
-      than one segment, we end up with more than one PE#.  There is a HW
-      mechanism to make the freeze state cascade to "companion" PEs but
-      that only works for PCIe error messages (typically used so that if
-      you freeze a switch, it freezes all its children).  So we do it in
-      SW.  We lose a bit of effectiveness of EEH in that case, but that's
-      the best we found.  So when any of the PEs freezes, we freeze the
-      other ones for that "domain".  We thus introduce the concept of
-      "master PE" which is the one used for DMA, MSIs, etc., and "secondary
-      PEs" that are used for the remaining M64 segments.
-
-    We would like to investigate using additional M64 windows in "single
-    PE" mode to overlay over specific BARs to work around some of that, for
-    example for devices with very large BARs, e.g., GPUs.  It would make
-    sense, but we haven't done it yet.
-
-3. Considerations for SR-IOV on PowerKVM
-
-  * SR-IOV Background
-
-    The PCIe SR-IOV feature allows a single Physical Function (PF) to
-    support several Virtual Functions (VFs).  Registers in the PF's SR-IOV
-    Capability control the number of VFs and whether they are enabled.
-
-    When VFs are enabled, they appear in Configuration Space like normal
-    PCI devices, but the BARs in VF config space headers are unusual.  For
-    a non-VF device, software uses BARs in the config space header to
-    discover the BAR sizes and assign addresses for them.  For VF devices,
-    software uses VF BAR registers in the *PF* SR-IOV Capability to
-    discover sizes and assign addresses.  The BARs in the VF's config space
-    header are read-only zeros.
-
-    When a VF BAR in the PF SR-IOV Capability is programmed, it sets the
-    base address for all the corresponding VF(n) BARs.  For example, if the
-    PF SR-IOV Capability is programmed to enable eight VFs, and it has a
-    1MB VF BAR0, the address in that VF BAR sets the base of an 8MB region.
-    This region is divided into eight contiguous 1MB regions, each of which
-    is a BAR0 for one of the VFs.  Note that even though the VF BAR
-    describes an 8MB region, the alignment requirement is for a single VF,
-    i.e., 1MB in this example.
-
-  There are several strategies for isolating VFs in PEs:
-
-  - M32 window: There's one M32 window, and it is split into 256
-    equally-sized segments.  The finest granularity possible is a 256MB
-    window with 1MB segments.  VF BARs that are 1MB or larger could be
-    mapped to separate PEs in this window.  Each segment can be
-    individually mapped to a PE via the lookup table, so this is quite
-    flexible, but it works best when all the VF BARs are the same size.  If
-    they are different sizes, the entire window has to be small enough that
-    the segment size matches the smallest VF BAR, which means larger VF
-    BARs span several segments.
-
-  - Non-segmented M64 window: A non-segmented M64 window is mapped entirely
-    to a single PE, so it could only isolate one VF.
-
-  - Single segmented M64 windows: A segmented M64 window could be used just
-    like the M32 window, but the segments can't be individually mapped to
-    PEs (the segment number is the PE#), so there isn't as much
-    flexibility.  A VF with multiple BARs would have to be in a "domain" of
-    multiple PEs, which is not as well isolated as a single PE.
-
-  - Multiple segmented M64 windows: As usual, each window is split into 256
-    equally-sized segments, and the segment number is the PE#.  But if we
-    use several M64 windows, they can be set to different base addresses
-    and different segment sizes.  If we have VFs that each have a 1MB BAR
-    and a 32MB BAR, we could use one M64 window to assign 1MB segments and
-    another M64 window to assign 32MB segments.
-
-  Finally, the plan to use M64 windows for SR-IOV, which will be described
-  more in the next two sections.  For a given VF BAR, we need to
-  effectively reserve the entire 256 segments (256 * VF BAR size) and
-  position the VF BAR to start at the beginning of a free range of
-  segments/PEs inside that M64 window.
-
-  The goal is of course to be able to give a separate PE for each VF.
-
-  The IODA2 platform has 16 M64 windows, which are used to map MMIO
-  range to PE#.  Each M64 window defines one MMIO range and this range is
-  divided into 256 segments, with each segment corresponding to one PE.
-
-  We decide to leverage this M64 window to map VFs to individual PEs, since
-  SR-IOV VF BARs are all the same size.
-
-  But doing so introduces another problem: total_VFs is usually smaller
-  than the number of M64 window segments, so if we map one VF BAR directly
-  to one M64 window, some part of the M64 window will map to another
-  device's MMIO range.
-
-  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:
-
-     0      1                     total_VFs - 1
-     +------+------+-     -+------+------+
-     |      |      |  ...  |      |      |
-     +------+------+-     -+------+------+
-
-                           VF(n) BAR space
-
-     0      1                     total_VFs - 1                255
-     +------+------+-     -+------+------+-      -+------+------+
-     |      |      |  ...  |      |      |   ...  |      |      |
-     +------+------+-     -+------+------+-      -+------+------+
-
-                           M64 window
-
-               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:
-
-     0      1                     total_VFs - 1                255
-     +------+------+-     -+------+------+-      -+------+------+
-     |      |      |  ...  |      |      |   ...  |      |      |
-     +------+------+-     -+------+------+-      -+------+------+
-
-                           VF(n) BAR space + extra
-
-     0      1                     total_VFs - 1                255
-     +------+------+-     -+------+------+-      -+------+------+
-     |      |      |  ...  |      |      |   ...  |      |      |
-     +------+------+-     -+------+------+-      -+------+------+
-
-                          M64 window
-
-               Figure 1.1 Map VF(n) BAR space + extra
-
-  Allocating the extra space ensures that the entire M64 window will be
-  assigned to this one SR-IOV device and none of the space will be
-  available for other devices.  Note that this only expands the space
-  reserved in software; there are still only total_VFs VFs, and they only
-  respond to segments [0, total_VFs - 1].  There's nothing in hardware that
-  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.
-
-In IODA2, the MMIO address determines the PE#.  If the address is in an M32
-window, we can set the PE# by updating the table that translates segments
-to PE#s.  Similarly, if the address is in an unsegmented M64 window, we can
-set the PE# for the window.  But if it's in a segmented M64 window, the
-segment number is the PE#.
-
-Therefore, the only way to control the PE# for a VF is to change the base
-of the VF(n) BAR space in the VF BAR.  If the PCI core allocates the exact
-amount of space required for the VF(n) BAR space, the VF BAR value is fixed
-and cannot be changed.
-
-On the other hand, if the PCI core allocates additional space, the VF BAR
-value can be changed as long as the entire VF(n) BAR space remains inside
-the space allocated by the core.
-
-Ideally the segment size will be the same as an individual VF BAR size.
-Then each VF will be in its own PE.  The VF BARs (and therefore the PE#s)
-are contiguous.  If VF0 is in PE(x), then VF(n) is in PE(x+n).  If we
-allocate 256 segments, there are (256 - numVFs) choices for the PE# of VF0.
-
-If the segment size is smaller than the VF BAR size, it will take several
-segments to cover a VF BAR, and a VF will be in several PEs.  This is
-possible, but the isolation isn't as good, and it reduces the number of PE#
-choices because instead of consuming only numVFs segments, the VF(n) BAR
-space will consume (numVFs * n) segments.  That means there aren't as many
-available segments for adjusting base of the VF(n) BAR space.
diff --git a/Documentation/powerpc/pmu-ebb.rst b/Documentation/powerpc/pmu-ebb.rst
new file mode 100644 (file)
index 0000000..4f47475
--- /dev/null
@@ -0,0 +1,138 @@
+========================
+PMU Event Based Branches
+========================
+
+Event Based Branches (EBBs) are a feature which allows the hardware to
+branch directly to a specified user space address when certain events occur.
+
+The full specification is available in Power ISA v2.07:
+
+  https://www.power.org/documentation/power-isa-version-2-07/
+
+One type of event for which EBBs can be configured is PMU exceptions. This
+document describes the API for configuring the Power PMU to generate EBBs,
+using the Linux perf_events API.
+
+
+Terminology
+-----------
+
+Throughout this document we will refer to an "EBB event" or "EBB events". This
+just refers to a struct perf_event which has set the "EBB" flag in its
+attr.config. All events which can be configured on the hardware PMU are
+possible "EBB events".
+
+
+Background
+----------
+
+When a PMU EBB occurs it is delivered to the currently running process. As such
+EBBs can only sensibly be used by programs for self-monitoring.
+
+It is a feature of the perf_events API that events can be created on other
+processes, subject to standard permission checks. This is also true of EBB
+events, however unless the target process enables EBBs (via mtspr(BESCR)) no
+EBBs will ever be delivered.
+
+This makes it possible for a process to enable EBBs for itself, but not
+actually configure any events. At a later time another process can come along
+and attach an EBB event to the process, which will then cause EBBs to be
+delivered to the first process. It's not clear if this is actually useful.
+
+
+When the PMU is configured for EBBs, all PMU interrupts are delivered to the
+user process. This means once an EBB event is scheduled on the PMU, no non-EBB
+events can be configured. This means that EBB events can not be run
+concurrently with regular 'perf' commands, or any other perf events.
+
+It is however safe to run 'perf' commands on a process which is using EBBs. The
+kernel will in general schedule the EBB event, and perf will be notified that
+its events could not run.
+
+The exclusion between EBB events and regular events is implemented using the
+existing "pinned" and "exclusive" attributes of perf_events. This means EBB
+events will be given priority over other events, unless they are also pinned.
+If an EBB event and a regular event are both pinned, then whichever is enabled
+first will be scheduled and the other will be put in error state. See the
+section below titled "Enabling an EBB event" for more information.
+
+
+Creating an EBB event
+---------------------
+
+To request that an event is counted using EBB, the event code should have bit
+63 set.
+
+EBB events must be created with a particular, and restrictive, set of
+attributes - this is so that they interoperate correctly with the rest of the
+perf_events subsystem.
+
+An EBB event must be created with the "pinned" and "exclusive" attributes set.
+Note that if you are creating a group of EBB events, only the leader can have
+these attributes set.
+
+An EBB event must NOT set any of the "inherit", "sample_period", "freq" or
+"enable_on_exec" attributes.
+
+An EBB event must be attached to a task. This is specified to perf_event_open()
+by passing a pid value, typically 0 indicating the current task.
+
+All events in a group must agree on whether they want EBB. That is all events
+must request EBB, or none may request EBB.
+
+EBB events must specify the PMC they are to be counted on. This ensures
+userspace is able to reliably determine which PMC the event is scheduled on.
+
+
+Enabling an EBB event
+---------------------
+
+Once an EBB event has been successfully opened, it must be enabled with the
+perf_events API. This can be achieved either via the ioctl() interface, or the
+prctl() interface.
+
+However, due to the design of the perf_events API, enabling an event does not
+guarantee that it has been scheduled on the PMU. To ensure that the EBB event
+has been scheduled on the PMU, you must perform a read() on the event. If the
+read() returns EOF, then the event has not been scheduled and EBBs are not
+enabled.
+
+This behaviour occurs because the EBB event is pinned and exclusive. When the
+EBB event is enabled it will force all other non-pinned events off the PMU. In
+this case the enable will be successful. However if there is already an event
+pinned on the PMU then the enable will not be successful.
+
+
+Reading an EBB event
+--------------------
+
+It is possible to read() from an EBB event. However the results are
+meaningless. Because interrupts are being delivered to the user process the
+kernel is not able to count the event, and so will return a junk value.
+
+
+Closing an EBB event
+--------------------
+
+When an EBB event is finished with, you can close it using close() as for any
+regular event. If this is the last EBB event the PMU will be deconfigured and
+no further PMU EBBs will be delivered.
+
+
+EBB Handler
+-----------
+
+The EBB handler is just regular userspace code, however it must be written in
+the style of an interrupt handler. When the handler is entered all registers
+are live (possibly) and so must be saved somehow before the handler can invoke
+other code.
+
+It's up to the program how to handle this. For C programs a relatively simple
+option is to create an interrupt frame on the stack and save registers there.
+
+Fork
+----
+
+EBB events are not inherited across fork. If the child process wishes to use
+EBBs it should open a new event for itself. Similarly the EBB state in
+BESCR/EBBHR/EBBRR is cleared across fork().
diff --git a/Documentation/powerpc/pmu-ebb.txt b/Documentation/powerpc/pmu-ebb.txt
deleted file mode 100644 (file)
index 73cd163..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-PMU Event Based Branches
-========================
-
-Event Based Branches (EBBs) are a feature which allows the hardware to
-branch directly to a specified user space address when certain events occur.
-
-The full specification is available in Power ISA v2.07:
-
-  https://www.power.org/documentation/power-isa-version-2-07/
-
-One type of event for which EBBs can be configured is PMU exceptions. This
-document describes the API for configuring the Power PMU to generate EBBs,
-using the Linux perf_events API.
-
-
-Terminology
------------
-
-Throughout this document we will refer to an "EBB event" or "EBB events". This
-just refers to a struct perf_event which has set the "EBB" flag in its
-attr.config. All events which can be configured on the hardware PMU are
-possible "EBB events".
-
-
-Background
-----------
-
-When a PMU EBB occurs it is delivered to the currently running process. As such
-EBBs can only sensibly be used by programs for self-monitoring.
-
-It is a feature of the perf_events API that events can be created on other
-processes, subject to standard permission checks. This is also true of EBB
-events, however unless the target process enables EBBs (via mtspr(BESCR)) no
-EBBs will ever be delivered.
-
-This makes it possible for a process to enable EBBs for itself, but not
-actually configure any events. At a later time another process can come along
-and attach an EBB event to the process, which will then cause EBBs to be
-delivered to the first process. It's not clear if this is actually useful.
-
-
-When the PMU is configured for EBBs, all PMU interrupts are delivered to the
-user process. This means once an EBB event is scheduled on the PMU, no non-EBB
-events can be configured. This means that EBB events can not be run
-concurrently with regular 'perf' commands, or any other perf events.
-
-It is however safe to run 'perf' commands on a process which is using EBBs. The
-kernel will in general schedule the EBB event, and perf will be notified that
-its events could not run.
-
-The exclusion between EBB events and regular events is implemented using the
-existing "pinned" and "exclusive" attributes of perf_events. This means EBB
-events will be given priority over other events, unless they are also pinned.
-If an EBB event and a regular event are both pinned, then whichever is enabled
-first will be scheduled and the other will be put in error state. See the
-section below titled "Enabling an EBB event" for more information.
-
-
-Creating an EBB event
----------------------
-
-To request that an event is counted using EBB, the event code should have bit
-63 set.
-
-EBB events must be created with a particular, and restrictive, set of
-attributes - this is so that they interoperate correctly with the rest of the
-perf_events subsystem.
-
-An EBB event must be created with the "pinned" and "exclusive" attributes set.
-Note that if you are creating a group of EBB events, only the leader can have
-these attributes set.
-
-An EBB event must NOT set any of the "inherit", "sample_period", "freq" or
-"enable_on_exec" attributes.
-
-An EBB event must be attached to a task. This is specified to perf_event_open()
-by passing a pid value, typically 0 indicating the current task.
-
-All events in a group must agree on whether they want EBB. That is all events
-must request EBB, or none may request EBB.
-
-EBB events must specify the PMC they are to be counted on. This ensures
-userspace is able to reliably determine which PMC the event is scheduled on.
-
-
-Enabling an EBB event
----------------------
-
-Once an EBB event has been successfully opened, it must be enabled with the
-perf_events API. This can be achieved either via the ioctl() interface, or the
-prctl() interface.
-
-However, due to the design of the perf_events API, enabling an event does not
-guarantee that it has been scheduled on the PMU. To ensure that the EBB event
-has been scheduled on the PMU, you must perform a read() on the event. If the
-read() returns EOF, then the event has not been scheduled and EBBs are not
-enabled.
-
-This behaviour occurs because the EBB event is pinned and exclusive. When the
-EBB event is enabled it will force all other non-pinned events off the PMU. In
-this case the enable will be successful. However if there is already an event
-pinned on the PMU then the enable will not be successful.
-
-
-Reading an EBB event
---------------------
-
-It is possible to read() from an EBB event. However the results are
-meaningless. Because interrupts are being delivered to the user process the
-kernel is not able to count the event, and so will return a junk value.
-
-
-Closing an EBB event
---------------------
-
-When an EBB event is finished with, you can close it using close() as for any
-regular event. If this is the last EBB event the PMU will be deconfigured and
-no further PMU EBBs will be delivered.
-
-
-EBB Handler
------------
-
-The EBB handler is just regular userspace code, however it must be written in
-the style of an interrupt handler. When the handler is entered all registers
-are live (possibly) and so must be saved somehow before the handler can invoke
-other code.
-
-It's up to the program how to handle this. For C programs a relatively simple
-option is to create an interrupt frame on the stack and save registers there.
-
-Fork
-----
-
-EBB events are not inherited across fork. If the child process wishes to use
-EBBs it should open a new event for itself. Similarly the EBB state in
-BESCR/EBBHR/EBBRR is cleared across fork().
diff --git a/Documentation/powerpc/ptrace.rst b/Documentation/powerpc/ptrace.rst
new file mode 100644 (file)
index 0000000..864d4b6
--- /dev/null
@@ -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 (file)
index 99c5ce8..0000000
+++ /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.rst b/Documentation/powerpc/qe_firmware.rst
new file mode 100644 (file)
index 0000000..42f5103
--- /dev/null
@@ -0,0 +1,296 @@
+=========================================
+Freescale QUICC Engine Firmware Uploading
+=========================================
+
+(c) 2007 Timur Tabi <timur at freescale.com>,
+    Freescale Semiconductor
+
+.. Table of Contents
+
+   I - Software License for Firmware
+
+   II - Microcode Availability
+
+   III - Description and Terminology
+
+   IV - Microcode Programming Details
+
+   V - Firmware Structure Layout
+
+   VI - Sample Code for Creating Firmware Files
+
+Revision Information
+====================
+
+November 30, 2007: Rev 1.0 - Initial version
+
+I - Software License for Firmware
+=================================
+
+Each firmware file comes with its own software license.  For information on
+the particular license, please see the license text that is distributed with
+the firmware.
+
+II - Microcode Availability
+===========================
+
+Firmware files are distributed through various channels.  Some are available on
+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.
+
+The term 'firmware' refers to a binary blob that contains the microcode as
+well as other data that
+
+       1) describes the microcode's purpose
+       2) describes how and where to upload the microcode
+       3) specifies the values of various registers
+       4) includes additional data for use by specific device drivers
+
+Firmware files are binary files that contain only a firmware.
+
+IV - Microcode Programming Details
+===================================
+
+The QE architecture allows for only one microcode present in I-RAM for each
+RISC processor.  To replace any current microcode, a full QE reset (which
+disables the microcode) must be performed first.
+
+QE microcode is uploaded using the following procedure:
+
+1) The microcode is placed into I-RAM at a specific location, using the
+   IRAM.IADD and IRAM.IDATA registers.
+
+2) The CERCR.CIR bit is set to 0 or 1, depending on whether the firmware
+   needs split I-RAM.  Split I-RAM is only meaningful for SOCs that have
+   QEs with multiple RISC processors, such as the 8360.  Splitting the I-RAM
+   allows each processor to run a different microcode, effectively creating an
+   asymmetric multiprocessing (AMP) system.
+
+3) The TIBCR trap registers are loaded with the addresses of the trap handlers
+   in the microcode.
+
+4) The RSP.ECCR register is programmed with the value provided.
+
+5) If necessary, device drivers that need the virtual traps and extended mode
+   data will use them.
+
+Virtual Microcode Traps
+
+These virtual traps are conditional branches in the microcode.  These are
+"soft" provisional introduced in the ROMcode in order to enable higher
+flexibility and save h/w traps If new features are activated or an issue is
+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::
+
+       ---------------------------------------------------------------
+       | Offset in |                  | Destination Offset | Size of |
+       |   array   |     Protocol     |   within PRAM      | Operand |
+       --------------------------------------------------------------|
+       |     0     | Ethernet         |      0xF8          | 4 bytes |
+       |           | interworking     |                    |         |
+       ---------------------------------------------------------------
+       |     4     | ATM              |      0xF8          | 4 bytes |
+       |           | interworking     |                    |         |
+       ---------------------------------------------------------------
+       |     8     | PPP              |      0xF8          | 4 bytes |
+       |           | interworking     |                    |         |
+       ---------------------------------------------------------------
+       |     12    | Ethernet RX      |      0x22          | 1 byte  |
+       |           | Distributor Page |                    |         |
+       ---------------------------------------------------------------
+       |     16    | ATM Globtal      |      0x28          | 1 byte  |
+       |           | Params Table     |                    |         |
+       ---------------------------------------------------------------
+       |     20    | Insert Frame     |      0xF8          | 4 bytes |
+       ---------------------------------------------------------------
+
+
+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::
+
+       -----------------------------------------------------------------------
+       | Bit #  |     Name     |   Description                               |
+       -----------------------------------------------------------------------
+       |   0    | General      | Indicates that prior to each host command   |
+       |        | push command | given by the application, the software must |
+       |        |              | assert a special host command (push command)|
+       |        |              | CECDR = 0x00800000.                         |
+       |        |              | CECR = 0x01c1000f.                          |
+       -----------------------------------------------------------------------
+       |   1    | UCC ATM      | Indicates that after issuing ATM RX INIT    |
+       |        | RX INIT      | command, the host must issue another special|
+       |        | push command | command (push command) and immediately      |
+       |        |              | following that re-issue the ATM RX INIT     |
+       |        |              | command. (This makes the sequence of        |
+       |        |              | initializing the ATM receiver a sequence of |
+       |        |              | three host commands)                        |
+       |        |              | CECDR = 0x00800000.                         |
+       |        |              | CECR = 0x01c1000f.                          |
+       -----------------------------------------------------------------------
+       |   2    | Add/remove   | Indicates that following the specific host  |
+       |        | command      | command: "Add/Remove entry in Hash Lookup   |
+       |        | validation   | Table" used in Interworking setup, the user |
+       |        |              | must issue another command.                 |
+       |        |              | CECDR = 0xce000003.                         |
+       |        |              | CECR = 0x01c10f58.                          |
+       -----------------------------------------------------------------------
+       |   3    | General push | Indicates that the s/w has to initialize    |
+       |        | command      | some pointers in the Ethernet thread pages  |
+       |        |              | which are used when Header Compression is   |
+       |        |              | activated.  The full details of these       |
+       |        |              | pointers is located in the software drivers.|
+       -----------------------------------------------------------------------
+       |   4    | General push | Indicates that after issuing Ethernet TX    |
+       |        | command      | INIT command, user must issue this command  |
+       |        |              | for each SNUM of Ethernet TX thread.        |
+       |        |              | CECDR = 0x00800003.                         |
+       |        |              | CECR = 0x7'b{0}, 8'b{Enet TX thread SNUM},  |
+       |        |              |        1'b{1}, 12'b{0}, 4'b{1}              |
+       -----------------------------------------------------------------------
+       | 5 - 31 |     N/A      | Reserved, set to zero.                      |
+       -----------------------------------------------------------------------
+
+V - Firmware Structure Layout
+==============================
+
+QE microcode from Freescale is typically provided as a header file.  This
+header file contains macros that define the microcode binary itself as well as
+some other data used in uploading that microcode.  The format of these files
+do not lend themselves to simple inclusion into other code.  Hence,
+the need for a more portable format.  This section defines that format.
+
+Instead of distributing a header file, the microcode and related data are
+embedded into a binary blob.  This blob is passed to the qe_upload_firmware()
+function, which parses the blob and performs everything necessary to upload
+the microcode.
+
+All integers are big-endian.  See the comments for function
+qe_upload_firmware() for up-to-date implementation information.
+
+This structure supports versioning, where the version of the structure is
+embedded into the structure itself.  To ensure forward and backwards
+compatibility, all versions of the structure must use the same 'qe_header'
+structure at the beginning.
+
+'header' (type: struct qe_header):
+       The 'length' field is the size, in bytes, of the entire structure,
+       including all the microcode embedded in it, as well as the CRC (if
+       present).
+
+       The 'magic' field is an array of three bytes that contains the letters
+       'Q', 'E', and 'F'.  This is an identifier that indicates that this
+       structure is a QE Firmware structure.
+
+       The 'version' field is a single byte that indicates the version of this
+       structure.  If the layout of the structure should ever need to be
+       changed to add support for additional types of microcode, then the
+       version number should also be changed.
+
+The 'id' field is a null-terminated string(suitable for printing) that
+identifies the firmware.
+
+The 'count' field indicates the number of 'microcode' structures.  There
+must be one and only one 'microcode' structure for each RISC processor.
+Therefore, this field also represents the number of RISC processors for this
+SOC.
+
+The 'soc' structure contains the SOC numbers and revisions used to match
+the microcode to the SOC itself.  Normally, the microcode loader should
+check the data in this structure with the SOC number and revisions, and
+only upload the microcode if there's a match.  However, this check is not
+made on all platforms.
+
+Although it is not recommended, you can specify '0' in the soc.model
+field to skip matching SOCs altogether.
+
+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::
+
+     soc.model = 8323
+     soc.major = 1
+     soc.minor = 0
+
+'padding' is necessary for structure alignment.  This field ensures that the
+'extended_modes' field is aligned on a 64-bit boundary.
+
+'extended_modes' is a bitfield that defines special functionality which has an
+impact on the device drivers.  Each bit has its own impact and has special
+instructions for the driver associated with it.  This field is stored in
+the QE library and available to any driver that calles qe_get_firmware_info().
+
+'vtraps' is an array of 8 words that contain virtual trap values for each
+virtual traps.  As with 'extended_modes', this field is stored in the QE
+library and available to any driver that calles qe_get_firmware_info().
+
+'microcode' (type: struct qe_microcode):
+       For each RISC processor there is one 'microcode' structure.  The first
+       'microcode' structure is for the first RISC, and so on.
+
+       The 'id' field is a null-terminated string suitable for printing that
+       identifies this particular microcode.
+
+       'traps' is an array of 16 words that contain hardware trap values
+       for each of the 16 traps.  If trap[i] is 0, then this particular
+       trap is to be ignored (i.e. not written to TIBCR[i]).  The entire value
+       is written as-is to the TIBCR[i] register, so be sure to set the EN
+       and T_IBP bits if necessary.
+
+       'eccr' is the value to program into the ECCR register.
+
+       'iram_offset' is the offset into IRAM to start writing the
+       microcode.
+
+       'count' is the number of 32-bit words in the microcode.
+
+       'code_offset' is the offset, in bytes, from the beginning of this
+       structure where the microcode itself can be found.  The first
+       microcode binary should be located immediately after the 'microcode'
+       array.
+
+       'major', 'minor', and 'revision' are the major, minor, and revision
+       version numbers, respectively, of the microcode.  If all values are 0,
+       then these fields are ignored.
+
+       'reserved' is necessary for structure alignment.  Since 'microcode'
+       is an array, the 64-bit 'extended_modes' field needs to be aligned
+       on a 64-bit boundary, and this can only happen if the size of
+       'microcode' is a multiple of 8 bytes.  To ensure that, we add
+       'reserved'.
+
+After the last microcode is a 32-bit CRC.  It can be calculated using
+this algorithm::
+
+  u32 crc32(const u8 *p, unsigned int len)
+  {
+       unsigned int i;
+       u32 crc = 0;
+
+       while (len--) {
+          crc ^= *p++;
+          for (i = 0; i < 8; i++)
+                  crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
+       }
+       return crc;
+  }
+
+VI - Sample Code for Creating Firmware Files
+============================================
+
+A Python program that creates firmware binaries from the header files normally
+distributed by Freescale can be found on http://opensource.freescale.com.
diff --git a/Documentation/powerpc/qe_firmware.txt b/Documentation/powerpc/qe_firmware.txt
deleted file mode 100644 (file)
index e7ac24a..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-          Freescale QUICC Engine Firmware Uploading
-          -----------------------------------------
-
-(c) 2007 Timur Tabi <timur at freescale.com>,
-    Freescale Semiconductor
-
-Table of Contents
-=================
-
-  I - Software License for Firmware
-
-  II - Microcode Availability
-
-  III - Description and Terminology
-
-  IV - Microcode Programming Details
-
-  V - Firmware Structure Layout
-
-  VI - Sample Code for Creating Firmware Files
-
-Revision Information
-====================
-
-November 30, 2007: Rev 1.0 - Initial version
-
-I - Software License for Firmware
-=================================
-
-Each firmware file comes with its own software license.  For information on
-the particular license, please see the license text that is distributed with
-the firmware.
-
-II - Microcode Availability
-===========================
-
-Firmware files are distributed through various channels.  Some are available on
-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.
-
-The term 'firmware' refers to a binary blob that contains the microcode as
-well as other data that
-
-       1) describes the microcode's purpose
-       2) describes how and where to upload the microcode
-       3) specifies the values of various registers
-       4) includes additional data for use by specific device drivers
-
-Firmware files are binary files that contain only a firmware.
-
-IV - Microcode Programming Details
-===================================
-
-The QE architecture allows for only one microcode present in I-RAM for each
-RISC processor.  To replace any current microcode, a full QE reset (which
-disables the microcode) must be performed first.
-
-QE microcode is uploaded using the following procedure:
-
-1) The microcode is placed into I-RAM at a specific location, using the
-   IRAM.IADD and IRAM.IDATA registers.
-
-2) The CERCR.CIR bit is set to 0 or 1, depending on whether the firmware
-   needs split I-RAM.  Split I-RAM is only meaningful for SOCs that have
-   QEs with multiple RISC processors, such as the 8360.  Splitting the I-RAM
-   allows each processor to run a different microcode, effectively creating an
-   asymmetric multiprocessing (AMP) system.
-
-3) The TIBCR trap registers are loaded with the addresses of the trap handlers
-   in the microcode.
-
-4) The RSP.ECCR register is programmed with the value provided.
-
-5) If necessary, device drivers that need the virtual traps and extended mode
-   data will use them.
-
-Virtual Microcode Traps
-
-These virtual traps are conditional branches in the microcode.  These are
-"soft" provisional introduced in the ROMcode in order to enable higher
-flexibility and save h/w traps If new features are activated or an issue is
-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.
-
-       ---------------------------------------------------------------
-       | Offset in |                  | Destination Offset | Size of |
-       |   array   |     Protocol     |   within PRAM      | Operand |
-       --------------------------------------------------------------|
-       |     0     | Ethernet         |      0xF8          | 4 bytes |
-       |           | interworking     |                    |         |
-       ---------------------------------------------------------------
-       |     4     | ATM              |      0xF8          | 4 bytes |
-       |           | interworking     |                    |         |
-       ---------------------------------------------------------------
-       |     8     | PPP              |      0xF8          | 4 bytes |
-       |           | interworking     |                    |         |
-       ---------------------------------------------------------------
-       |     12    | Ethernet RX      |      0x22          | 1 byte  |
-       |           | Distributor Page |                    |         |
-       ---------------------------------------------------------------
-       |     16    | ATM Globtal      |      0x28          | 1 byte  |
-       |           | Params Table     |                    |         |
-       ---------------------------------------------------------------
-       |     20    | Insert Frame     |      0xF8          | 4 bytes |
-       ---------------------------------------------------------------
-
-
-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:
-
-       -----------------------------------------------------------------------
-       | Bit #  |     Name     |   Description                               |
-       -----------------------------------------------------------------------
-       |   0    | General      | Indicates that prior to each host command   |
-       |        | push command | given by the application, the software must |
-       |        |              | assert a special host command (push command)|
-       |        |              | CECDR = 0x00800000.                         |
-       |        |              | CECR = 0x01c1000f.                          |
-       -----------------------------------------------------------------------
-       |   1    | UCC ATM      | Indicates that after issuing ATM RX INIT    |
-       |        | RX INIT      | command, the host must issue another special|
-       |        | push command | command (push command) and immediately      |
-       |        |              | following that re-issue the ATM RX INIT     |
-       |        |              | command. (This makes the sequence of        |
-       |        |              | initializing the ATM receiver a sequence of |
-       |        |              | three host commands)                        |
-       |        |              | CECDR = 0x00800000.                         |
-       |        |              | CECR = 0x01c1000f.                          |
-       -----------------------------------------------------------------------
-       |   2    | Add/remove   | Indicates that following the specific host  |
-       |        | command      | command: "Add/Remove entry in Hash Lookup   |
-       |        | validation   | Table" used in Interworking setup, the user |
-       |        |              | must issue another command.                 |
-       |        |              | CECDR = 0xce000003.                         |
-       |        |              | CECR = 0x01c10f58.                          |
-       -----------------------------------------------------------------------
-       |   3    | General push | Indicates that the s/w has to initialize    |
-       |        | command      | some pointers in the Ethernet thread pages  |
-       |        |              | which are used when Header Compression is   |
-       |        |              | activated.  The full details of these       |
-       |        |              | pointers is located in the software drivers.|
-       -----------------------------------------------------------------------
-       |   4    | General push | Indicates that after issuing Ethernet TX    |
-       |        | command      | INIT command, user must issue this command  |
-       |        |              | for each SNUM of Ethernet TX thread.        |
-       |        |              | CECDR = 0x00800003.                         |
-       |        |              | CECR = 0x7'b{0}, 8'b{Enet TX thread SNUM},  |
-       |        |              |        1'b{1}, 12'b{0}, 4'b{1}              |
-       -----------------------------------------------------------------------
-       | 5 - 31 |     N/A      | Reserved, set to zero.                      |
-       -----------------------------------------------------------------------
-
-V - Firmware Structure Layout
-==============================
-
-QE microcode from Freescale is typically provided as a header file.  This
-header file contains macros that define the microcode binary itself as well as
-some other data used in uploading that microcode.  The format of these files
-do not lend themselves to simple inclusion into other code.  Hence,
-the need for a more portable format.  This section defines that format.
-
-Instead of distributing a header file, the microcode and related data are
-embedded into a binary blob.  This blob is passed to the qe_upload_firmware()
-function, which parses the blob and performs everything necessary to upload
-the microcode.
-
-All integers are big-endian.  See the comments for function
-qe_upload_firmware() for up-to-date implementation information.
-
-This structure supports versioning, where the version of the structure is
-embedded into the structure itself.  To ensure forward and backwards
-compatibility, all versions of the structure must use the same 'qe_header'
-structure at the beginning.
-
-'header' (type: struct qe_header):
-       The 'length' field is the size, in bytes, of the entire structure,
-       including all the microcode embedded in it, as well as the CRC (if
-       present).
-
-       The 'magic' field is an array of three bytes that contains the letters
-       'Q', 'E', and 'F'.  This is an identifier that indicates that this
-       structure is a QE Firmware structure.
-
-       The 'version' field is a single byte that indicates the version of this
-       structure.  If the layout of the structure should ever need to be
-       changed to add support for additional types of microcode, then the
-       version number should also be changed.
-
-The 'id' field is a null-terminated string(suitable for printing) that
-identifies the firmware.
-
-The 'count' field indicates the number of 'microcode' structures.  There
-must be one and only one 'microcode' structure for each RISC processor.
-Therefore, this field also represents the number of RISC processors for this
-SOC.
-
-The 'soc' structure contains the SOC numbers and revisions used to match
-the microcode to the SOC itself.  Normally, the microcode loader should
-check the data in this structure with the SOC number and revisions, and
-only upload the microcode if there's a match.  However, this check is not
-made on all platforms.
-
-Although it is not recommended, you can specify '0' in the soc.model
-field to skip matching SOCs altogether.
-
-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:
-     soc.model = 8323
-     soc.major = 1
-     soc.minor = 0
-
-'padding' is necessary for structure alignment.  This field ensures that the
-'extended_modes' field is aligned on a 64-bit boundary.
-
-'extended_modes' is a bitfield that defines special functionality which has an
-impact on the device drivers.  Each bit has its own impact and has special
-instructions for the driver associated with it.  This field is stored in
-the QE library and available to any driver that calles qe_get_firmware_info().
-
-'vtraps' is an array of 8 words that contain virtual trap values for each
-virtual traps.  As with 'extended_modes', this field is stored in the QE
-library and available to any driver that calles qe_get_firmware_info().
-
-'microcode' (type: struct qe_microcode):
-       For each RISC processor there is one 'microcode' structure.  The first
-       'microcode' structure is for the first RISC, and so on.
-
-       The 'id' field is a null-terminated string suitable for printing that
-       identifies this particular microcode.
-
-       'traps' is an array of 16 words that contain hardware trap values
-       for each of the 16 traps.  If trap[i] is 0, then this particular
-       trap is to be ignored (i.e. not written to TIBCR[i]).  The entire value
-       is written as-is to the TIBCR[i] register, so be sure to set the EN
-       and T_IBP bits if necessary.
-
-       'eccr' is the value to program into the ECCR register.
-
-       'iram_offset' is the offset into IRAM to start writing the
-       microcode.
-
-       'count' is the number of 32-bit words in the microcode.
-
-       'code_offset' is the offset, in bytes, from the beginning of this
-       structure where the microcode itself can be found.  The first
-       microcode binary should be located immediately after the 'microcode'
-       array.
-
-       'major', 'minor', and 'revision' are the major, minor, and revision
-       version numbers, respectively, of the microcode.  If all values are 0,
-       then these fields are ignored.
-
-       'reserved' is necessary for structure alignment.  Since 'microcode'
-       is an array, the 64-bit 'extended_modes' field needs to be aligned
-       on a 64-bit boundary, and this can only happen if the size of
-       'microcode' is a multiple of 8 bytes.  To ensure that, we add
-       'reserved'.
-
-After the last microcode is a 32-bit CRC.  It can be calculated using
-this algorithm:
-
-u32 crc32(const u8 *p, unsigned int len)
-{
-       unsigned int i;
-       u32 crc = 0;
-
-       while (len--) {
-          crc ^= *p++;
-          for (i = 0; i < 8; i++)
-                  crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
-       }
-       return crc;
-}
-
-VI - Sample Code for Creating Firmware Files
-============================================
-
-A Python program that creates firmware binaries from the header files normally
-distributed by Freescale can be found on http://opensource.freescale.com.
diff --git a/Documentation/powerpc/syscall64-abi.rst b/Documentation/powerpc/syscall64-abi.rst
new file mode 100644 (file)
index 0000000..e49f69f
--- /dev/null
@@ -0,0 +1,110 @@
+===============================================
+Power Architecture 64-bit Linux system call ABI
+===============================================
+
+syscall
+=======
+
+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.
+
+.. [1] Some syscalls (typically low-level management functions) may have
+       different calling sequences (e.g., rt_sigreturn).
+
+Parameters and return value
+---------------------------
+The system call number is specified in r0.
+
+There is a maximum of 6 integer parameters to a syscall, passed in r3-r8.
+
+Both a return value and a return error code are returned. cr0.SO is the return
+error code, and r3 is the return value or error code. When cr0.SO is clear,
+the syscall succeeded and r3 is the return value. When cr0.SO is set, the
+syscall failed and r3 is the error code that generally corresponds to errno.
+
+Stack
+-----
+System calls do not modify the caller's stack frame. For example, the caller's
+stack frame LR and CR save fields are not used.
+
+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
+=========== ============= ========================================
+
+All floating point and vector data registers as well as control and status
+registers are nonvolatile.
+
+Invocation
+----------
+The syscall is performed with the sc instruction, and returns with execution
+continuing at the instruction following the sc instruction.
+
+Transactional Memory
+--------------------
+Syscall behavior can change if the processor is in transactional or suspended
+transaction state, and the syscall can affect the behavior of the transaction.
+
+If the processor is in suspended state when a syscall is made, the syscall
+will be performed as normal, and will return as normal. The syscall will be
+performed in suspended state, so its side effects will be persistent according
+to the usual transactional memory semantics. A syscall may or may not result
+in the transaction being doomed by hardware.
+
+If the processor is in transactional state when a syscall is made, then the
+behavior depends on the presence of PPC_FEATURE2_HTM_NOSC in the AT_HWCAP2 ELF
+auxiliary vector.
+
+- If present, which is the case for newer kernels, then the syscall will not
+  be performed and the transaction will be doomed by the kernel with the
+  failure code TM_CAUSE_SYSCALL | TM_CAUSE_PERSISTENT in the TEXASR SPR.
+
+- If not present (older kernels), then the kernel will suspend the
+  transactional state and the syscall will proceed as in the case of a
+  suspended state syscall, and will resume the transactional state before
+  returning to the caller. This case is not well defined or supported, so this
+  behavior should not be relied upon.
+
+
+vsyscall
+========
+
+vsyscall calling sequence matches the syscall calling sequence, with the
+following differences. Some vsyscalls may have different calling sequences.
+
+Parameters and return value
+---------------------------
+r0 is not used as an input. The vsyscall is selected by its address.
+
+Stack
+-----
+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
+=========== ========
+
+Invocation
+----------
+The vsyscall is performed with a branch-with-link instruction to the vsyscall
+function address.
+
+Transactional Memory
+--------------------
+vsyscalls will run in the same transactional state as the caller. A vsyscall
+may or may not result in the transaction being doomed by hardware.
diff --git a/Documentation/powerpc/syscall64-abi.txt b/Documentation/powerpc/syscall64-abi.txt
deleted file mode 100644 (file)
index fa716a0..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-===============================================
-Power Architecture 64-bit Linux system call ABI
-===============================================
-
-syscall
-=======
-
-syscall calling sequence[*] 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).
-
-Parameters and return value
----------------------------
-The system call number is specified in r0.
-
-There is a maximum of 6 integer parameters to a syscall, passed in r3-r8.
-
-Both a return value and a return error code are returned. cr0.SO is the return
-error code, and r3 is the return value or error code. When cr0.SO is clear,
-the syscall succeeded and r3 is the return value. When cr0.SO is set, the
-syscall failed and r3 is the error code that generally corresponds to errno.
-
-Stack
------
-System calls do not modify the caller's stack frame. For example, the caller's
-stack frame LR and CR save fields are not used.
-
-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.
-
-All floating point and vector data registers as well as control and status
-registers are nonvolatile.
-
-Invocation
-----------
-The syscall is performed with the sc instruction, and returns with execution
-continuing at the instruction following the sc instruction.
-
-Transactional Memory
---------------------
-Syscall behavior can change if the processor is in transactional or suspended
-transaction state, and the syscall can affect the behavior of the transaction.
-
-If the processor is in suspended state when a syscall is made, the syscall
-will be performed as normal, and will return as normal. The syscall will be
-performed in suspended state, so its side effects will be persistent according
-to the usual transactional memory semantics. A syscall may or may not result
-in the transaction being doomed by hardware.
-
-If the processor is in transactional state when a syscall is made, then the
-behavior depends on the presence of PPC_FEATURE2_HTM_NOSC in the AT_HWCAP2 ELF
-auxiliary vector.
-
-- If present, which is the case for newer kernels, then the syscall will not
-  be performed and the transaction will be doomed by the kernel with the
-  failure code TM_CAUSE_SYSCALL | TM_CAUSE_PERSISTENT in the TEXASR SPR.
-
-- If not present (older kernels), then the kernel will suspend the
-  transactional state and the syscall will proceed as in the case of a
-  suspended state syscall, and will resume the transactional state before
-  returning to the caller. This case is not well defined or supported, so this
-  behavior should not be relied upon.
-
-
-vsyscall
-========
-
-vsyscall calling sequence matches the syscall calling sequence, with the
-following differences. Some vsyscalls may have different calling sequences.
-
-Parameters and return value
----------------------------
-r0 is not used as an input. The vsyscall is selected by its address.
-
-Stack
------
-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.
-
-Invocation
-----------
-The vsyscall is performed with a branch-with-link instruction to the vsyscall
-function address.
-
-Transactional Memory
---------------------
-vsyscalls will run in the same transactional state as the caller. A vsyscall
-may or may not result in the transaction being doomed by hardware.
diff --git a/Documentation/powerpc/transactional_memory.rst b/Documentation/powerpc/transactional_memory.rst
new file mode 100644 (file)
index 0000000..0995510
--- /dev/null
@@ -0,0 +1,247 @@
+============================
+Transactional Memory support
+============================
+
+POWER kernel support for this feature is currently limited to supporting
+its use by user programs.  It is not currently used by the kernel itself.
+
+This file aims to sum up how it is supported by Linux and what behaviour you
+can expect from your user programs.
+
+
+Basic overview
+==============
+
+Hardware Transactional Memory is supported on POWER8 processors, and is a
+feature that enables a different form of atomic memory access.  Several new
+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::
+
+  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)
+
+    tend
+
+    b     continue
+
+  abort_handler:
+    ... test for odd failures ...
+
+    /* 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.
+Between these points the processor is in 'Transactional' state; any memory
+references will complete in one go if there are no conflicts with other
+transactional or non-transactional accesses within the system.  In this
+example, the transaction completes as though it were normal straight-line code
+IF no other processor has touched SAVINGS_ACCT(r3) or CURRENT_ACCT(r3); an
+atomic move of money from the current account to the savings account has been
+performed.  Even though the normal ld/std instructions are used (note no
+lwarx/stwcx), either *both* SAVINGS_ACCT(r3) and CURRENT_ACCT(r3) will be
+updated, or neither will be updated.
+
+If, in the meantime, there is a conflict with the locations accessed by the
+transaction, the transaction will be aborted by the CPU.  Register and memory
+state will roll back to that at the 'tbegin', and control will continue from
+'tbegin+4'.  The branch to abort_handler will be taken this second time; the
+abort handler can check the cause of the failure, and retry.
+
+Checkpointed registers include all GPRs, FPRs, VRs/VSRs, LR, CCR/CR, CTR, FPCSR
+and a few other status/flag regs; see the ISA for details.
+
+Causes of transaction aborts
+============================
+
+- Conflicts with cache lines used by other processors
+- Signals
+- Context switches
+- See the ISA for full documentation of everything that will abort transactions.
+
+
+Syscalls
+========
+
+Syscalls made from within an active transaction will not be performed and the
+transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL
+| TM_CAUSE_PERSISTENT.
+
+Syscalls made from within a suspended transaction are performed as normal and
+the transaction is not explicitly doomed by the kernel.  However, what the
+kernel does to perform the syscall may result in the transaction being doomed
+by the hardware.  The syscall is performed in suspended mode so any side
+effects will be persistent, independent of transaction success or failure.  No
+guarantees are provided by the kernel about which syscalls will affect
+transaction success.
+
+Care must be taken when relying on syscalls to abort during active transactions
+if the calls are made via a library.  Libraries may cache values (which may
+give the appearance of success) or perform operations that cause transaction
+failure before entering the kernel (which may produce different failure codes).
+Examples are glibc's getpid() and lazy symbol resolution.
+
+
+Signals
+=======
+
+Delivery of signals (both sync and async) during transactions provides a second
+thread state (ucontext/mcontext) to represent the second transactional register
+state.  Signal delivery 'treclaim's to capture both register states, so signals
+abort transactions.  The usual ucontext_t passed to the signal handler
+represents the checkpointed/original register state; the signal appears to have
+arisen at 'tbegin+4'.
+
+If the sighandler ucontext has uc_link set, a second ucontext has been
+delivered.  For future compatibility the MSR.TS field should be checked to
+determine the transactional state -- if so, the second ucontext in uc->uc_link
+represents the active transactional registers at the point of the signal.
+
+For 64-bit processes, uc->uc_mcontext.regs->msr is a full 64-bit MSR and its TS
+field shows the transactional mode.
+
+For 32-bit processes, the mcontext's MSR register is only 32 bits; the top 32
+bits are stored in the MSR of the second ucontext, i.e. in
+uc->uc_link->uc_mcontext.regs->msr.  The top word contains the transactional
+state TS.
+
+However, basic signal handlers don't need to be aware of transactions
+and simply returning from the handler will deal with things correctly:
+
+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::
+
+    void crash_handler(int sig, siginfo_t *si, void *uc)
+    {
+      ucontext_t *ucp = uc;
+      ucontext_t *transactional_ucp = ucp->uc_link;
+
+      if (ucp_link) {
+        u64 msr = ucp->uc_mcontext.regs->msr;
+        /* May have transactional ucontext! */
+  #ifndef __powerpc64__
+        msr |= ((u64)transactional_ucp->uc_mcontext.regs->msr) << 32;
+  #endif
+        if (MSR_TM_ACTIVE(msr)) {
+           /* Yes, we crashed during a transaction.  Oops. */
+   fprintf(stderr, "Transaction to be restarted at 0x%llx, but "
+                           "crashy instruction was at 0x%llx\n",
+                           ucp->uc_mcontext.regs->nip,
+                           transactional_ucp->uc_mcontext.regs->nip);
+        }
+      }
+
+      fix_the_problem(ucp->dar);
+    }
+
+When in an active transaction that takes a signal, we need to be careful with
+the stack.  It's possible that the stack has moved back up after the tbegin.
+The obvious case here is when the tbegin is called inside a function that
+returns before a tend.  In this case, the stack is part of the checkpointed
+transactional memory state.  If we write over this non transactionally or in
+suspend, we are in trouble because if we get a tm abort, the program counter and
+stack pointer will be back at the tbegin but our in memory stack won't be valid
+anymore.
+
+To avoid this, when taking a signal in an active transaction, we need to use
+the stack pointer from the checkpointed state, rather than the speculated
+state.  This ensures that the signal context (written tm suspended) will be
+written below the stack required for the rollback.  The transaction is aborted
+because of the treclaim, so any memory written between the tbegin and the
+signal will be rolled back anyway.
+
+For signals taken in non-TM or suspended mode, we use the
+normal/non-checkpointed stack pointer.
+
+Any transaction initiated inside a sighandler and suspended on return
+from the sighandler to the kernel will get reclaimed and discarded.
+
+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.
+ TM_CAUSE_SYSCALL       Syscall from active transaction.
+ TM_CAUSE_SIGNAL        Signal delivered.
+ 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
+a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.
+
+GDB
+===
+
+GDB and ptrace are not currently TM-aware.  If one stops during a transaction,
+it looks like the transaction has just started (the checkpointed state is
+presented).  The transaction cannot then be continued and will take the failure
+handler route.  Furthermore, the transactional 2nd register state will be
+inaccessible.  GDB can currently be used on programs using TM, but not sensibly
+in parts within transactions.
+
+POWER9
+======
+
+TM on POWER9 has issues with storing the complete register state. This
+is described in this commit::
+
+    commit 4bb3c7a0208fc13ca70598efd109901a7cd45ae7
+    Author: Paul Mackerras <paulus@ozlabs.org>
+    Date:   Wed Mar 21 21:32:01 2018 +1100
+    KVM: PPC: Book3S HV: Work around transactional memory bugs in POWER9
+
+To account for this different POWER9 chips have TM enabled in
+different ways.
+
+On POWER9N DD2.01 and below, TM is disabled. ie
+HWCAP2[PPC_FEATURE2_HTM] is not set.
+
+On POWER9N DD2.1 TM is configured by firmware to always abort a
+transaction when tm suspend occurs. So tsuspend will cause a
+transaction to be aborted and rolled back. Kernel exceptions will also
+cause the transaction to be aborted and rolled back and the exception
+will not occur. If userspace constructs a sigcontext that enables TM
+suspend, the sigcontext will be rejected by the kernel. This mode is
+advertised to users with HWCAP2[PPC_FEATURE2_HTM_NO_SUSPEND] set.
+HWCAP2[PPC_FEATURE2_HTM] is not set in this mode.
+
+On POWER9N DD2.2 and above, KVM and POWERVM emulate TM for guests (as
+described in commit 4bb3c7a0208f), hence TM is enabled for guests
+ie. HWCAP2[PPC_FEATURE2_HTM] is set for guest userspace. Guests that
+makes heavy use of TM suspend (tsuspend or kernel suspend) will result
+in traps into the hypervisor and hence will suffer a performance
+degradation. Host userspace has TM disabled
+ie. HWCAP2[PPC_FEATURE2_HTM] is not set. (although we make enable it
+at some point in the future if we bring the emulation into host
+userspace context switching).
+
+POWER9C DD1.2 and above are only available with POWERVM and hence
+Linux only runs as a guest. On these systems TM is emulated like on
+POWER9N DD2.2.
+
+Guest migration from POWER8 to POWER9 will work with POWER9N DD2.2 and
+POWER9C DD1.2. Since earlier POWER9 processors don't support TM
+emulation, migration from POWER8 to POWER9 is not supported there.
diff --git a/Documentation/powerpc/transactional_memory.txt b/Documentation/powerpc/transactional_memory.txt
deleted file mode 100644 (file)
index 52c023e..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-Transactional Memory support
-============================
-
-POWER kernel support for this feature is currently limited to supporting
-its use by user programs.  It is not currently used by the kernel itself.
-
-This file aims to sum up how it is supported by Linux and what behaviour you
-can expect from your user programs.
-
-
-Basic overview
-==============
-
-Hardware Transactional Memory is supported on POWER8 processors, and is a
-feature that enables a different form of atomic memory access.  Several new
-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:
-
-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)
-
-  tend
-
-  b     continue
-
-abort_handler:
-  ... test for odd failures ...
-
-  /* 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.
-Between these points the processor is in 'Transactional' state; any memory
-references will complete in one go if there are no conflicts with other
-transactional or non-transactional accesses within the system.  In this
-example, the transaction completes as though it were normal straight-line code
-IF no other processor has touched SAVINGS_ACCT(r3) or CURRENT_ACCT(r3); an
-atomic move of money from the current account to the savings account has been
-performed.  Even though the normal ld/std instructions are used (note no
-lwarx/stwcx), either *both* SAVINGS_ACCT(r3) and CURRENT_ACCT(r3) will be
-updated, or neither will be updated.
-
-If, in the meantime, there is a conflict with the locations accessed by the
-transaction, the transaction will be aborted by the CPU.  Register and memory
-state will roll back to that at the 'tbegin', and control will continue from
-'tbegin+4'.  The branch to abort_handler will be taken this second time; the
-abort handler can check the cause of the failure, and retry.
-
-Checkpointed registers include all GPRs, FPRs, VRs/VSRs, LR, CCR/CR, CTR, FPCSR
-and a few other status/flag regs; see the ISA for details.
-
-Causes of transaction aborts
-============================
-
-- Conflicts with cache lines used by other processors
-- Signals
-- Context switches
-- See the ISA for full documentation of everything that will abort transactions.
-
-
-Syscalls
-========
-
-Syscalls made from within an active transaction will not be performed and the
-transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL
-| TM_CAUSE_PERSISTENT.
-
-Syscalls made from within a suspended transaction are performed as normal and
-the transaction is not explicitly doomed by the kernel.  However, what the
-kernel does to perform the syscall may result in the transaction being doomed
-by the hardware.  The syscall is performed in suspended mode so any side
-effects will be persistent, independent of transaction success or failure.  No
-guarantees are provided by the kernel about which syscalls will affect
-transaction success.
-
-Care must be taken when relying on syscalls to abort during active transactions
-if the calls are made via a library.  Libraries may cache values (which may
-give the appearance of success) or perform operations that cause transaction
-failure before entering the kernel (which may produce different failure codes).
-Examples are glibc's getpid() and lazy symbol resolution.
-
-
-Signals
-=======
-
-Delivery of signals (both sync and async) during transactions provides a second
-thread state (ucontext/mcontext) to represent the second transactional register
-state.  Signal delivery 'treclaim's to capture both register states, so signals
-abort transactions.  The usual ucontext_t passed to the signal handler
-represents the checkpointed/original register state; the signal appears to have
-arisen at 'tbegin+4'.
-
-If the sighandler ucontext has uc_link set, a second ucontext has been
-delivered.  For future compatibility the MSR.TS field should be checked to
-determine the transactional state -- if so, the second ucontext in uc->uc_link
-represents the active transactional registers at the point of the signal.
-
-For 64-bit processes, uc->uc_mcontext.regs->msr is a full 64-bit MSR and its TS
-field shows the transactional mode.
-
-For 32-bit processes, the mcontext's MSR register is only 32 bits; the top 32
-bits are stored in the MSR of the second ucontext, i.e. in
-uc->uc_link->uc_mcontext.regs->msr.  The top word contains the transactional
-state TS.
-
-However, basic signal handlers don't need to be aware of transactions
-and simply returning from the handler will deal with things correctly:
-
-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:
-
-    void crash_handler(int sig, siginfo_t *si, void *uc)
-    {
-      ucontext_t *ucp = uc;
-      ucontext_t *transactional_ucp = ucp->uc_link;
-
-      if (ucp_link) {
-        u64 msr = ucp->uc_mcontext.regs->msr;
-        /* May have transactional ucontext! */
-#ifndef __powerpc64__
-        msr |= ((u64)transactional_ucp->uc_mcontext.regs->msr) << 32;
-#endif
-        if (MSR_TM_ACTIVE(msr)) {
-           /* Yes, we crashed during a transaction.  Oops. */
-   fprintf(stderr, "Transaction to be restarted at 0x%llx, but "
-                           "crashy instruction was at 0x%llx\n",
-                           ucp->uc_mcontext.regs->nip,
-                           transactional_ucp->uc_mcontext.regs->nip);
-        }
-      }
-
-      fix_the_problem(ucp->dar);
-    }
-
-When in an active transaction that takes a signal, we need to be careful with
-the stack.  It's possible that the stack has moved back up after the tbegin.
-The obvious case here is when the tbegin is called inside a function that
-returns before a tend.  In this case, the stack is part of the checkpointed
-transactional memory state.  If we write over this non transactionally or in
-suspend, we are in trouble because if we get a tm abort, the program counter and
-stack pointer will be back at the tbegin but our in memory stack won't be valid
-anymore.
-
-To avoid this, when taking a signal in an active transaction, we need to use
-the stack pointer from the checkpointed state, rather than the speculated
-state.  This ensures that the signal context (written tm suspended) will be
-written below the stack required for the rollback.  The transaction is aborted
-because of the treclaim, so any memory written between the tbegin and the
-signal will be rolled back anyway.
-
-For signals taken in non-TM or suspended mode, we use the
-normal/non-checkpointed stack pointer.
-
-Any transaction initiated inside a sighandler and suspended on return
-from the sighandler to the kernel will get reclaimed and discarded.
-
-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.
- TM_CAUSE_SYSCALL       Syscall from active transaction.
- TM_CAUSE_SIGNAL        Signal delivered.
- 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
-a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.
-
-GDB
-===
-
-GDB and ptrace are not currently TM-aware.  If one stops during a transaction,
-it looks like the transaction has just started (the checkpointed state is
-presented).  The transaction cannot then be continued and will take the failure
-handler route.  Furthermore, the transactional 2nd register state will be
-inaccessible.  GDB can currently be used on programs using TM, but not sensibly
-in parts within transactions.
-
-POWER9
-======
-
-TM on POWER9 has issues with storing the complete register state. This
-is described in this commit:
-
-    commit 4bb3c7a0208fc13ca70598efd109901a7cd45ae7
-    Author: Paul Mackerras <paulus@ozlabs.org>
-    Date:   Wed Mar 21 21:32:01 2018 +1100
-    KVM: PPC: Book3S HV: Work around transactional memory bugs in POWER9
-
-To account for this different POWER9 chips have TM enabled in
-different ways.
-
-On POWER9N DD2.01 and below, TM is disabled. ie
-HWCAP2[PPC_FEATURE2_HTM] is not set.
-
-On POWER9N DD2.1 TM is configured by firmware to always abort a
-transaction when tm suspend occurs. So tsuspend will cause a
-transaction to be aborted and rolled back. Kernel exceptions will also
-cause the transaction to be aborted and rolled back and the exception
-will not occur. If userspace constructs a sigcontext that enables TM
-suspend, the sigcontext will be rejected by the kernel. This mode is
-advertised to users with HWCAP2[PPC_FEATURE2_HTM_NO_SUSPEND] set.
-HWCAP2[PPC_FEATURE2_HTM] is not set in this mode.
-
-On POWER9N DD2.2 and above, KVM and POWERVM emulate TM for guests (as
-described in commit 4bb3c7a0208f), hence TM is enabled for guests
-ie. HWCAP2[PPC_FEATURE2_HTM] is set for guest userspace. Guests that
-makes heavy use of TM suspend (tsuspend or kernel suspend) will result
-in traps into the hypervisor and hence will suffer a performance
-degradation. Host userspace has TM disabled
-ie. HWCAP2[PPC_FEATURE2_HTM] is not set. (although we make enable it
-at some point in the future if we bring the emulation into host
-userspace context switching).
-
-POWER9C DD1.2 and above are only available with POWERVM and hence
-Linux only runs as a guest. On these systems TM is emulated like on
-POWER9N DD2.2.
-
-Guest migration from POWER8 to POWER9 will work with POWER9N DD2.2 and
-POWER9C DD1.2. Since earlier POWER9 processors don't support TM
-emulation, migration from POWER8 to POWER9 is not supported there.
diff --git a/Documentation/process/conf.py b/Documentation/process/conf.py
deleted file mode 100644 (file)
index 1b01a80..0000000
+++ /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'),
-]
index 49e0f64..053b24a 100644 (file)
@@ -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.
index 1e210c6..fca9c4f 100644 (file)
@@ -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/sh/conf.py b/Documentation/sh/conf.py
deleted file mode 100644 (file)
index 1eb684a..0000000
+++ /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 (file)
index 3f1fc5e..0000000
+++ /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'),
-]
index 301a21a..eeb394b 100644 (file)
@@ -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)
index 1739cba..f1ad450 100644 (file)
@@ -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
index 2eda85d..012de0f 100644 (file)
@@ -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
index 7bd70d6..38e0a95 100644 (file)
@@ -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.
index 276db0e..118fb41 100644 (file)
@@ -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 (file)
index 0000000..f4b0063
--- /dev/null
@@ -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
index a33c2a5..2774624 100644 (file)
@@ -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 (file)
index 2eaf59f..0000000
+++ /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/virt/index.rst b/Documentation/virt/index.rst
new file mode 100644 (file)
index 0000000..062ffb5
--- /dev/null
@@ -0,0 +1,18 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================
+Linux Virtualization Support
+============================
+
+.. toctree::
+   :maxdepth: 2
+
+   kvm/index
+   paravirt_ops
+
+.. only:: html and subproject
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/virt/kvm/amd-memory-encryption.rst b/Documentation/virt/kvm/amd-memory-encryption.rst
new file mode 100644 (file)
index 0000000..d18c97b
--- /dev/null
@@ -0,0 +1,250 @@
+======================================
+Secure Encrypted Virtualization (SEV)
+======================================
+
+Overview
+========
+
+Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
+
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When enabled,
+the memory contents of a VM will be transparently encrypted with a key
+unique to that VM.
+
+The hypervisor can determine the SEV support through the CPUID
+instruction. The CPUID function 0x8000001f reports information related
+to SEV::
+
+       0x8000001f[eax]:
+                       Bit[1]  indicates support for SEV
+           ...
+                 [ecx]:
+                       Bits[31:0]  Number of encrypted guests supported simultaneously
+
+If support for SEV is present, MSR 0xc001_0010 (MSR_K8_SYSCFG) and MSR 0xc001_0015
+(MSR_K7_HWCR) can be used to determine if it can be enabled::
+
+       0xc001_0010:
+               Bit[23]    1 = memory encryption can be enabled
+                          0 = memory encryption can not be enabled
+
+       0xc001_0015:
+               Bit[0]     1 = memory encryption can be enabled
+                          0 = memory encryption can not be enabled
+
+When SEV support is available, it can be enabled in a specific VM by
+setting the SEV bit before executing VMRUN.::
+
+       VMCB[0x90]:
+               Bit[1]      1 = SEV is enabled
+                           0 = SEV is disabled
+
+SEV hardware uses ASIDs to associate a memory encryption key with a VM.
+Hence, the ASID for the SEV-enabled guests must be from 1 to a maximum value
+defined in the CPUID 0x8000001f[ecx] field.
+
+SEV Key Management
+==================
+
+The SEV guest key management is handled by a separate processor called the AMD
+Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a secure
+key management interface to perform common hypervisor activities such as
+encrypting bootstrap code, snapshot, migrating and debugging the guest. For more
+information, see the SEV Key Management spec [api-spec]_
+
+KVM implements the following commands to support common lifecycle events of SEV
+guests, such as launching, running, snapshotting, migrating and decommissioning.
+
+1. KVM_SEV_INIT
+---------------
+
+The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform
+context. In a typical workflow, this command should be the first command issued.
+
+Returns: 0 on success, -negative on error
+
+2. KVM_SEV_LAUNCH_START
+-----------------------
+
+The KVM_SEV_LAUNCH_START command is used for creating the memory encryption
+context. To create the encryption context, user must provide a guest policy,
+the owner's public Diffie-Hellman (PDH) key and session information.
+
+Parameters: struct  kvm_sev_launch_start (in/out)
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_start {
+                __u32 handle;           /* if zero then firmware creates a new handle */
+                __u32 policy;           /* guest's policy */
+
+                __u64 dh_uaddr;         /* userspace address pointing to the guest owner's PDH key */
+                __u32 dh_len;
+
+                __u64 session_addr;     /* userspace address which points to the guest session information */
+                __u32 session_len;
+        };
+
+On success, the 'handle' field contains a new handle and on error, a negative value.
+
+For more details, see SEV spec Section 6.2.
+
+3. KVM_SEV_LAUNCH_UPDATE_DATA
+-----------------------------
+
+The KVM_SEV_LAUNCH_UPDATE_DATA is used for encrypting a memory region. It also
+calculates a measurement of the memory contents. The measurement is a signature
+of the memory contents that can be sent to the guest owner as an attestation
+that the memory was encrypted correctly by the firmware.
+
+Parameters (in): struct  kvm_sev_launch_update_data
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_update {
+                __u64 uaddr;    /* userspace address to be encrypted (must be 16-byte aligned) */
+                __u32 len;      /* length of the data to be encrypted (must be 16-byte aligned) */
+        };
+
+For more details, see SEV spec Section 6.3.
+
+4. KVM_SEV_LAUNCH_MEASURE
+-------------------------
+
+The KVM_SEV_LAUNCH_MEASURE command is used to retrieve the measurement of the
+data encrypted by the KVM_SEV_LAUNCH_UPDATE_DATA command. The guest owner may
+wait to provide the guest with confidential information until it can verify the
+measurement. Since the guest owner knows the initial contents of the guest at
+boot, the measurement can be verified by comparing it to what the guest owner
+expects.
+
+Parameters (in): struct  kvm_sev_launch_measure
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_measure {
+                __u64 uaddr;    /* where to copy the measurement */
+                __u32 len;      /* length of measurement blob */
+        };
+
+For more details on the measurement verification flow, see SEV spec Section 6.4.
+
+5. KVM_SEV_LAUNCH_FINISH
+------------------------
+
+After completion of the launch flow, the KVM_SEV_LAUNCH_FINISH command can be
+issued to make the guest ready for the execution.
+
+Returns: 0 on success, -negative on error
+
+6. KVM_SEV_GUEST_STATUS
+-----------------------
+
+The KVM_SEV_GUEST_STATUS command is used to retrieve status information about a
+SEV-enabled guest.
+
+Parameters (out): struct kvm_sev_guest_status
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_guest_status {
+                __u32 handle;   /* guest handle */
+                __u32 policy;   /* guest policy */
+                __u8 state;     /* guest state (see enum below) */
+        };
+
+SEV guest state:
+
+::
+
+        enum {
+        SEV_STATE_INVALID = 0;
+        SEV_STATE_LAUNCHING,    /* guest is currently being launched */
+        SEV_STATE_SECRET,       /* guest is being launched and ready to accept the ciphertext data */
+        SEV_STATE_RUNNING,      /* guest is fully launched and running */
+        SEV_STATE_RECEIVING,    /* guest is being migrated in from another SEV machine */
+        SEV_STATE_SENDING       /* guest is getting migrated out to another SEV machine */
+        };
+
+7. KVM_SEV_DBG_DECRYPT
+----------------------
+
+The KVM_SEV_DEBUG_DECRYPT command can be used by the hypervisor to request the
+firmware to decrypt the data at the given memory region.
+
+Parameters (in): struct kvm_sev_dbg
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_dbg {
+                __u64 src_uaddr;        /* userspace address of data to decrypt */
+                __u64 dst_uaddr;        /* userspace address of destination */
+                __u32 len;              /* length of memory region to decrypt */
+        };
+
+The command returns an error if the guest policy does not allow debugging.
+
+8. KVM_SEV_DBG_ENCRYPT
+----------------------
+
+The KVM_SEV_DEBUG_ENCRYPT command can be used by the hypervisor to request the
+firmware to encrypt the data at the given memory region.
+
+Parameters (in): struct kvm_sev_dbg
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_dbg {
+                __u64 src_uaddr;        /* userspace address of data to encrypt */
+                __u64 dst_uaddr;        /* userspace address of destination */
+                __u32 len;              /* length of memory region to encrypt */
+        };
+
+The command returns an error if the guest policy does not allow debugging.
+
+9. KVM_SEV_LAUNCH_SECRET
+------------------------
+
+The KVM_SEV_LAUNCH_SECRET command can be used by the hypervisor to inject secret
+data after the measurement has been validated by the guest owner.
+
+Parameters (in): struct kvm_sev_launch_secret
+
+Returns: 0 on success, -negative on error
+
+::
+
+        struct kvm_sev_launch_secret {
+                __u64 hdr_uaddr;        /* userspace address containing the packet header */
+                __u32 hdr_len;
+
+                __u64 guest_uaddr;      /* the guest memory region where the secret should be injected */
+                __u32 guest_len;
+
+                __u64 trans_uaddr;      /* the hypervisor memory region which contains the secret */
+                __u32 trans_len;
+        };
+
+References
+==========
+
+
+See [white-paper]_, [api-spec]_, [amd-apm]_ and [kvm-forum]_ for more info.
+
+.. [white-paper] http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
+.. [api-spec] http://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
+.. [amd-apm] http://support.amd.com/TechDocs/24593.pdf (section 15.34)
+.. [kvm-forum]  http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
diff --git a/Documentation/virt/kvm/api.txt b/Documentation/virt/kvm/api.txt
new file mode 100644 (file)
index 0000000..2d06776
--- /dev/null
@@ -0,0 +1,5296 @@
+The Definitive KVM (Kernel-based Virtual Machine) API Documentation
+===================================================================
+
+1. General description
+----------------------
+
+The kvm API is a set of ioctls that are issued to control various aspects
+of a virtual machine.  The ioctls belong to three classes:
+
+ - System ioctls: These query and set global attributes which affect the
+   whole kvm subsystem.  In addition a system ioctl is used to create
+   virtual machines.
+
+ - VM ioctls: These query and set attributes that affect an entire virtual
+   machine, for example memory layout.  In addition a VM ioctl is used to
+   create virtual cpus (vcpus) and devices.
+
+   VM ioctls must be issued from the same process (address space) that was
+   used to create the VM.
+
+ - vcpu ioctls: These query and set attributes that control the operation
+   of a single virtual cpu.
+
+   vcpu ioctls should be issued from the same thread that was used to create
+   the vcpu, except for asynchronous vcpu ioctl that are marked as such in
+   the documentation.  Otherwise, the first ioctl after switching threads
+   could see a performance impact.
+
+ - device ioctls: These query and set attributes that control the operation
+   of a single device.
+
+   device ioctls must be issued from the same process (address space) that
+   was used to create the VM.
+
+2. File descriptors
+-------------------
+
+The kvm API is centered around file descriptors.  An initial
+open("/dev/kvm") obtains a handle to the kvm subsystem; this handle
+can be used to issue system ioctls.  A KVM_CREATE_VM ioctl on this
+handle will create a VM file descriptor which can be used to issue VM
+ioctls.  A KVM_CREATE_VCPU or KVM_CREATE_DEVICE ioctl on a VM fd will
+create a virtual cpu or device and return a file descriptor pointing to
+the new resource.  Finally, ioctls on a vcpu or device fd can be used
+to control the vcpu or device.  For vcpus, this includes the important
+task of actually running guest code.
+
+In general file descriptors can be migrated among processes by means
+of fork() and the SCM_RIGHTS facility of unix domain socket.  These
+kinds of tricks are explicitly not supported by kvm.  While they will
+not cause harm to the host, their actual behavior is not guaranteed by
+the API.  See "General description" for details on the ioctl usage
+model that is supported by KVM.
+
+It is important to note that althought VM ioctls may only be issued from
+the process that created the VM, a VM's lifecycle is associated with its
+file descriptor, not its creator (process).  In other words, the VM and
+its resources, *including the associated address space*, are not freed
+until the last reference to the VM's file descriptor has been released.
+For example, if fork() is issued after ioctl(KVM_CREATE_VM), the VM will
+not be freed until both the parent (original) process and its child have
+put their references to the VM's file descriptor.
+
+Because a VM's resources are not freed until the last reference to its
+file descriptor is released, creating additional references to a VM via
+via fork(), dup(), etc... without careful consideration is strongly
+discouraged and may have unwanted side effects, e.g. memory allocated
+by and on behalf of the VM's process may not be freed/unaccounted when
+the VM is shut down.
+
+
+3. Extensions
+-------------
+
+As of Linux 2.6.22, the KVM ABI has been stabilized: no backward
+incompatible change are allowed.  However, there is an extension
+facility that allows backward-compatible extensions to the API to be
+queried and used.
+
+The extension mechanism is not based on the Linux version number.
+Instead, kvm defines extension identifiers and a facility to query
+whether a particular extension identifier is available.  If it is, a
+set of ioctls is available for application use.
+
+
+4. API description
+------------------
+
+This section describes ioctls that can be used to control kvm guests.
+For each ioctl, the following information is provided along with a
+description:
+
+  Capability: which KVM extension provides this ioctl.  Can be 'basic',
+      which means that is will be provided by any kernel that supports
+      API version 12 (see section 4.1), a KVM_CAP_xyz constant, which
+      means availability needs to be checked with KVM_CHECK_EXTENSION
+      (see section 4.4), or 'none' which means that while not all kernels
+      support this ioctl, there's no capability bit to check its
+      availability: for kernels that don't support the ioctl,
+      the ioctl returns -ENOTTY.
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Type: system, vm, or vcpu.
+
+  Parameters: what parameters are accepted by the ioctl.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+
+4.1 KVM_GET_API_VERSION
+
+Capability: basic
+Architectures: all
+Type: system ioctl
+Parameters: none
+Returns: the constant KVM_API_VERSION (=12)
+
+This identifies the API version as the stable kvm API. It is not
+expected that this number will change.  However, Linux 2.6.20 and
+2.6.21 report earlier versions; these are not documented and not
+supported.  Applications should refuse to run if KVM_GET_API_VERSION
+returns a value other than 12.  If this check passes, all ioctls
+described as 'basic' will be available.
+
+
+4.2 KVM_CREATE_VM
+
+Capability: basic
+Architectures: all
+Type: system ioctl
+Parameters: machine type identifier (KVM_VM_*)
+Returns: a VM fd that can be used to control the new virtual machine.
+
+The new VM has no virtual cpus and no memory.
+You probably want to use 0 as machine type.
+
+In order to create user controlled virtual machines on S390, check
+KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
+privileged user (CAP_SYS_ADMIN).
+
+To use hardware assisted virtualization on MIPS (VZ ASE) rather than
+the default trap & emulate implementation (which changes the virtual
+memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
+flag KVM_VM_MIPS_VZ.
+
+
+On arm64, the physical address size for a VM (IPA Size limit) is limited
+to 40bits by default. The limit can be configured if the host supports the
+extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
+KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) to set the size in the machine type
+identifier, where IPA_Bits is the maximum width of any physical
+address used by the VM. The IPA_Bits is encoded in bits[7-0] of the
+machine type identifier.
+
+e.g, to configure a guest to use 48bit physical address size :
+
+    vm_fd = ioctl(dev_fd, KVM_CREATE_VM, KVM_VM_TYPE_ARM_IPA_SIZE(48));
+
+The requested size (IPA_Bits) must be :
+  0 - Implies default size, 40bits (for backward compatibility)
+
+  or
+
+  N - Implies N bits, where N is a positive integer such that,
+      32 <= N <= Host_IPA_Limit
+
+Host_IPA_Limit is the maximum possible value for IPA_Bits on the host and
+is dependent on the CPU capability and the kernel configuration. The limit can
+be retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the KVM_CHECK_EXTENSION
+ioctl() at run-time.
+
+Please note that configuring the IPA size does not affect the capability
+exposed by the guest CPUs in ID_AA64MMFR0_EL1[PARange]. It only affects
+size of the address translated by the stage2 level (guest physical to
+host physical address translations).
+
+
+4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
+
+Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
+Architectures: x86
+Type: system ioctl
+Parameters: struct kvm_msr_list (in/out)
+Returns: 0 on success; -1 on error
+Errors:
+  EFAULT:    the msr index list cannot be read from or written to
+  E2BIG:     the msr index list is to be to fit in the array specified by
+             the user.
+
+struct kvm_msr_list {
+       __u32 nmsrs; /* number of msrs in entries */
+       __u32 indices[0];
+};
+
+The user fills in the size of the indices array in nmsrs, and in return
+kvm adjusts nmsrs to reflect the actual number of msrs and fills in the
+indices array with their numbers.
+
+KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported.  The list
+varies by kvm version and host processor, but does not change otherwise.
+
+Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
+not returned in the MSR list, as different vcpus can have a different number
+of banks, as set via the KVM_X86_SETUP_MCE ioctl.
+
+KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed
+to the KVM_GET_MSRS system ioctl.  This lets userspace probe host capabilities
+and processor features that are exposed via MSRs (e.g., VMX capabilities).
+This list also varies by kvm version and host processor, but does not change
+otherwise.
+
+
+4.4 KVM_CHECK_EXTENSION
+
+Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
+Architectures: all
+Type: system ioctl, vm ioctl
+Parameters: extension identifier (KVM_CAP_*)
+Returns: 0 if unsupported; 1 (or some other positive integer) if supported
+
+The API allows the application to query about extensions to the core
+kvm API.  Userspace passes an extension identifier (an integer) and
+receives an integer that describes the extension availability.
+Generally 0 means no and 1 means yes, but some extensions may report
+additional information in the integer return value.
+
+Based on their initialization different VMs may have different capabilities.
+It is thus encouraged to use the vm ioctl to query for capabilities (available
+with KVM_CAP_CHECK_EXTENSION_VM on the vm fd)
+
+4.5 KVM_GET_VCPU_MMAP_SIZE
+
+Capability: basic
+Architectures: all
+Type: system ioctl
+Parameters: none
+Returns: size of vcpu mmap area, in bytes
+
+The KVM_RUN ioctl (cf.) communicates with userspace via a shared
+memory region.  This ioctl returns the size of that region.  See the
+KVM_RUN documentation for details.
+
+
+4.6 KVM_SET_MEMORY_REGION
+
+Capability: basic
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_memory_region (in)
+Returns: 0 on success, -1 on error
+
+This ioctl is obsolete and has been removed.
+
+
+4.7 KVM_CREATE_VCPU
+
+Capability: basic
+Architectures: all
+Type: vm ioctl
+Parameters: vcpu id (apic id on x86)
+Returns: vcpu fd on success, -1 on error
+
+This API adds a vcpu to a virtual machine. No more than max_vcpus may be added.
+The vcpu id is an integer in the range [0, max_vcpu_id).
+
+The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
+the KVM_CHECK_EXTENSION ioctl() at run-time.
+The maximum possible value for max_vcpus can be retrieved using the
+KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
+If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
+cpus max.
+If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
+same as the value returned from KVM_CAP_NR_VCPUS.
+
+The maximum possible value for max_vcpu_id can be retrieved using the
+KVM_CAP_MAX_VCPU_ID of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
+If the KVM_CAP_MAX_VCPU_ID does not exist, you should assume that max_vcpu_id
+is the same as the value returned from KVM_CAP_MAX_VCPUS.
+
+On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
+threads in one or more virtual CPU cores.  (This is because the
+hardware requires all the hardware threads in a CPU core to be in the
+same partition.)  The KVM_CAP_PPC_SMT capability indicates the number
+of vcpus per virtual core (vcore).  The vcore id is obtained by
+dividing the vcpu id by the number of vcpus per vcore.  The vcpus in a
+given vcore will always be in the same physical core as each other
+(though that might be a different physical core from time to time).
+Userspace can control the threading (SMT) mode of the guest by its
+allocation of vcpu ids.  For example, if userspace wants
+single-threaded guest vcpus, it should make all vcpu ids be a multiple
+of the number of vcpus per vcore.
+
+For virtual cpus that have been created with S390 user controlled virtual
+machines, the resulting vcpu fd can be memory mapped at page offset
+KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
+cpu's hardware control block.
+
+
+4.8 KVM_GET_DIRTY_LOG (vm ioctl)
+
+Capability: basic
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_dirty_log (in/out)
+Returns: 0 on success, -1 on error
+
+/* for KVM_GET_DIRTY_LOG */
+struct kvm_dirty_log {
+       __u32 slot;
+       __u32 padding;
+       union {
+               void __user *dirty_bitmap; /* one bit per page */
+               __u64 padding;
+       };
+};
+
+Given a memory slot, return a bitmap containing any pages dirtied
+since the last call to this ioctl.  Bit 0 is the first page in the
+memory slot.  Ensure the entire structure is cleared to avoid padding
+issues.
+
+If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
+the address space for which you want to return the dirty bitmap.
+They must be less than the value that KVM_CHECK_EXTENSION returns for
+the KVM_CAP_MULTI_ADDRESS_SPACE capability.
+
+The bits in the dirty bitmap are cleared before the ioctl returns, unless
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is enabled.  For more information,
+see the description of the capability.
+
+4.9 KVM_SET_MEMORY_ALIAS
+
+Capability: basic
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_memory_alias (in)
+Returns: 0 (success), -1 (error)
+
+This ioctl is obsolete and has been removed.
+
+
+4.10 KVM_RUN
+
+Capability: basic
+Architectures: all
+Type: vcpu ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+Errors:
+  EINTR:     an unmasked signal is pending
+
+This ioctl is used to run a guest virtual cpu.  While there are no
+explicit parameters, there is an implicit parameter block that can be
+obtained by mmap()ing the vcpu fd at offset 0, with the size given by
+KVM_GET_VCPU_MMAP_SIZE.  The parameter block is formatted as a 'struct
+kvm_run' (see below).
+
+
+4.11 KVM_GET_REGS
+
+Capability: basic
+Architectures: all except ARM, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_regs (out)
+Returns: 0 on success, -1 on error
+
+Reads the general purpose registers from the vcpu.
+
+/* x86 */
+struct kvm_regs {
+       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+       __u64 rax, rbx, rcx, rdx;
+       __u64 rsi, rdi, rsp, rbp;
+       __u64 r8,  r9,  r10, r11;
+       __u64 r12, r13, r14, r15;
+       __u64 rip, rflags;
+};
+
+/* mips */
+struct kvm_regs {
+       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
+       __u64 gpr[32];
+       __u64 hi;
+       __u64 lo;
+       __u64 pc;
+};
+
+
+4.12 KVM_SET_REGS
+
+Capability: basic
+Architectures: all except ARM, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_regs (in)
+Returns: 0 on success, -1 on error
+
+Writes the general purpose registers into the vcpu.
+
+See KVM_GET_REGS for the data structure.
+
+
+4.13 KVM_GET_SREGS
+
+Capability: basic
+Architectures: x86, ppc
+Type: vcpu ioctl
+Parameters: struct kvm_sregs (out)
+Returns: 0 on success, -1 on error
+
+Reads special registers from the vcpu.
+
+/* x86 */
+struct kvm_sregs {
+       struct kvm_segment cs, ds, es, fs, gs, ss;
+       struct kvm_segment tr, ldt;
+       struct kvm_dtable gdt, idt;
+       __u64 cr0, cr2, cr3, cr4, cr8;
+       __u64 efer;
+       __u64 apic_base;
+       __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
+};
+
+/* ppc -- see arch/powerpc/include/uapi/asm/kvm.h */
+
+interrupt_bitmap is a bitmap of pending external interrupts.  At most
+one bit may be set.  This interrupt has been acknowledged by the APIC
+but not yet injected into the cpu core.
+
+
+4.14 KVM_SET_SREGS
+
+Capability: basic
+Architectures: x86, ppc
+Type: vcpu ioctl
+Parameters: struct kvm_sregs (in)
+Returns: 0 on success, -1 on error
+
+Writes special registers into the vcpu.  See KVM_GET_SREGS for the
+data structures.
+
+
+4.15 KVM_TRANSLATE
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_translation (in/out)
+Returns: 0 on success, -1 on error
+
+Translates a virtual address according to the vcpu's current address
+translation mode.
+
+struct kvm_translation {
+       /* in */
+       __u64 linear_address;
+
+       /* out */
+       __u64 physical_address;
+       __u8  valid;
+       __u8  writeable;
+       __u8  usermode;
+       __u8  pad[5];
+};
+
+
+4.16 KVM_INTERRUPT
+
+Capability: basic
+Architectures: x86, ppc, mips
+Type: vcpu ioctl
+Parameters: struct kvm_interrupt (in)
+Returns: 0 on success, negative on failure.
+
+Queues a hardware interrupt vector to be injected.
+
+/* for KVM_INTERRUPT */
+struct kvm_interrupt {
+       /* in */
+       __u32 irq;
+};
+
+X86:
+
+Returns: 0 on success,
+        -EEXIST if an interrupt is already enqueued
+        -EINVAL the the irq number is invalid
+        -ENXIO if the PIC is in the kernel
+        -EFAULT if the pointer is invalid
+
+Note 'irq' is an interrupt vector, not an interrupt pin or line. This
+ioctl is useful if the in-kernel PIC is not used.
+
+PPC:
+
+Queues an external interrupt to be injected. This ioctl is overleaded
+with 3 different irq values:
+
+a) KVM_INTERRUPT_SET
+
+  This injects an edge type external interrupt into the guest once it's ready
+  to receive interrupts. When injected, the interrupt is done.
+
+b) KVM_INTERRUPT_UNSET
+
+  This unsets any pending interrupt.
+
+  Only available with KVM_CAP_PPC_UNSET_IRQ.
+
+c) KVM_INTERRUPT_SET_LEVEL
+
+  This injects a level type external interrupt into the guest context. The
+  interrupt stays pending until a specific ioctl with KVM_INTERRUPT_UNSET
+  is triggered.
+
+  Only available with KVM_CAP_PPC_IRQ_LEVEL.
+
+Note that any value for 'irq' other than the ones stated above is invalid
+and incurs unexpected behavior.
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+MIPS:
+
+Queues an external interrupt to be injected into the virtual CPU. A negative
+interrupt number dequeues the interrupt.
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+
+4.17 KVM_DEBUG_GUEST
+
+Capability: basic
+Architectures: none
+Type: vcpu ioctl
+Parameters: none)
+Returns: -1 on error
+
+Support for this has been removed.  Use KVM_SET_GUEST_DEBUG instead.
+
+
+4.18 KVM_GET_MSRS
+
+Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
+Architectures: x86
+Type: system ioctl, vcpu ioctl
+Parameters: struct kvm_msrs (in/out)
+Returns: number of msrs successfully returned;
+        -1 on error
+
+When used as a system ioctl:
+Reads the values of MSR-based features that are available for the VM.  This
+is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values.
+The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST
+in a system ioctl.
+
+When used as a vcpu ioctl:
+Reads model-specific registers from the vcpu.  Supported msr indices can
+be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
+
+struct kvm_msrs {
+       __u32 nmsrs; /* number of msrs in entries */
+       __u32 pad;
+
+       struct kvm_msr_entry entries[0];
+};
+
+struct kvm_msr_entry {
+       __u32 index;
+       __u32 reserved;
+       __u64 data;
+};
+
+Application code should set the 'nmsrs' member (which indicates the
+size of the entries array) and the 'index' member of each array entry.
+kvm will fill in the 'data' member.
+
+
+4.19 KVM_SET_MSRS
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_msrs (in)
+Returns: 0 on success, -1 on error
+
+Writes model-specific registers to the vcpu.  See KVM_GET_MSRS for the
+data structures.
+
+Application code should set the 'nmsrs' member (which indicates the
+size of the entries array), and the 'index' and 'data' members of each
+array entry.
+
+
+4.20 KVM_SET_CPUID
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_cpuid (in)
+Returns: 0 on success, -1 on error
+
+Defines the vcpu responses to the cpuid instruction.  Applications
+should use the KVM_SET_CPUID2 ioctl if available.
+
+
+struct kvm_cpuid_entry {
+       __u32 function;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding;
+};
+
+/* for KVM_SET_CPUID */
+struct kvm_cpuid {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry entries[0];
+};
+
+
+4.21 KVM_SET_SIGNAL_MASK
+
+Capability: basic
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_signal_mask (in)
+Returns: 0 on success, -1 on error
+
+Defines which signals are blocked during execution of KVM_RUN.  This
+signal mask temporarily overrides the threads signal mask.  Any
+unblocked signal received (except SIGKILL and SIGSTOP, which retain
+their traditional behaviour) will cause KVM_RUN to return with -EINTR.
+
+Note the signal will only be delivered if not blocked by the original
+signal mask.
+
+/* for KVM_SET_SIGNAL_MASK */
+struct kvm_signal_mask {
+       __u32 len;
+       __u8  sigset[0];
+};
+
+
+4.22 KVM_GET_FPU
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_fpu (out)
+Returns: 0 on success, -1 on error
+
+Reads the floating point state from the vcpu.
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+       __u8  fpr[8][16];
+       __u16 fcw;
+       __u16 fsw;
+       __u8  ftwx;  /* in fxsave format */
+       __u8  pad1;
+       __u16 last_opcode;
+       __u64 last_ip;
+       __u64 last_dp;
+       __u8  xmm[16][16];
+       __u32 mxcsr;
+       __u32 pad2;
+};
+
+
+4.23 KVM_SET_FPU
+
+Capability: basic
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_fpu (in)
+Returns: 0 on success, -1 on error
+
+Writes the floating point state to the vcpu.
+
+/* for KVM_GET_FPU and KVM_SET_FPU */
+struct kvm_fpu {
+       __u8  fpr[8][16];
+       __u16 fcw;
+       __u16 fsw;
+       __u8  ftwx;  /* in fxsave format */
+       __u8  pad1;
+       __u16 last_opcode;
+       __u64 last_ip;
+       __u64 last_dp;
+       __u8  xmm[16][16];
+       __u32 mxcsr;
+       __u32 pad2;
+};
+
+
+4.24 KVM_CREATE_IRQCHIP
+
+Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
+Architectures: x86, ARM, arm64, s390
+Type: vm ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+
+Creates an interrupt controller model in the kernel.
+On x86, creates a virtual ioapic, a virtual PIC (two PICs, nested), and sets up
+future vcpus to have a local APIC.  IRQ routing for GSIs 0-15 is set to both
+PIC and IOAPIC; GSI 16-23 only go to the IOAPIC.
+On ARM/arm64, a GICv2 is created. Any other GIC versions require the usage of
+KVM_CREATE_DEVICE, which also supports creating a GICv2.  Using
+KVM_CREATE_DEVICE is preferred over KVM_CREATE_IRQCHIP for GICv2.
+On s390, a dummy irq routing table is created.
+
+Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
+before KVM_CREATE_IRQCHIP can be used.
+
+
+4.25 KVM_IRQ_LINE
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86, arm, arm64
+Type: vm ioctl
+Parameters: struct kvm_irq_level
+Returns: 0 on success, -1 on error
+
+Sets the level of a GSI input to the interrupt controller model in the kernel.
+On some architectures it is required that an interrupt controller model has
+been previously created with KVM_CREATE_IRQCHIP.  Note that edge-triggered
+interrupts require the level to be set to 1 and then back to 0.
+
+On real hardware, interrupt pins can be active-low or active-high.  This
+does not matter for the level field of struct kvm_irq_level: 1 always
+means active (asserted), 0 means inactive (deasserted).
+
+x86 allows the operating system to program the interrupt polarity
+(active-low/active-high) for level-triggered interrupts, and KVM used
+to consider the polarity.  However, due to bitrot in the handling of
+active-low interrupts, the above convention is now valid on x86 too.
+This is signaled by KVM_CAP_X86_IOAPIC_POLARITY_IGNORED.  Userspace
+should not present interrupts to the guest as active-low unless this
+capability is present (or unless it is not using the in-kernel irqchip,
+of course).
+
+
+ARM/arm64 can signal an interrupt either at the CPU level, or at the
+in-kernel irqchip (GIC), and for in-kernel irqchip can tell the GIC to
+use PPIs designated for specific cpus.  The irq field is interpreted
+like this:
+
+  bits:  | 31 ... 24 | 23  ... 16 | 15    ...    0 |
+  field: | irq_type  | vcpu_index |     irq_id     |
+
+The irq_type field has the following values:
+- irq_type[0]: out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
+- irq_type[1]: in-kernel GIC: SPI, irq_id between 32 and 1019 (incl.)
+               (the vcpu_index field is ignored)
+- irq_type[2]: in-kernel GIC: PPI, irq_id between 16 and 31 (incl.)
+
+(The irq_id field thus corresponds nicely to the IRQ ID in the ARM GIC specs)
+
+In both cases, level is used to assert/deassert the line.
+
+struct kvm_irq_level {
+       union {
+               __u32 irq;     /* GSI */
+               __s32 status;  /* not used for KVM_IRQ_LEVEL */
+       };
+       __u32 level;           /* 0 or 1 */
+};
+
+
+4.26 KVM_GET_IRQCHIP
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_irqchip (in/out)
+Returns: 0 on success, -1 on error
+
+Reads the state of a kernel interrupt controller created with
+KVM_CREATE_IRQCHIP into a buffer provided by the caller.
+
+struct kvm_irqchip {
+       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
+       __u32 pad;
+        union {
+               char dummy[512];  /* reserving space */
+               struct kvm_pic_state pic;
+               struct kvm_ioapic_state ioapic;
+       } chip;
+};
+
+
+4.27 KVM_SET_IRQCHIP
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_irqchip (in)
+Returns: 0 on success, -1 on error
+
+Sets the state of a kernel interrupt controller created with
+KVM_CREATE_IRQCHIP from a buffer provided by the caller.
+
+struct kvm_irqchip {
+       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
+       __u32 pad;
+        union {
+               char dummy[512];  /* reserving space */
+               struct kvm_pic_state pic;
+               struct kvm_ioapic_state ioapic;
+       } chip;
+};
+
+
+4.28 KVM_XEN_HVM_CONFIG
+
+Capability: KVM_CAP_XEN_HVM
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_xen_hvm_config (in)
+Returns: 0 on success, -1 on error
+
+Sets the MSR that the Xen HVM guest uses to initialize its hypercall
+page, and provides the starting address and size of the hypercall
+blobs in userspace.  When the guest writes the MSR, kvm copies one
+page of a blob (32- or 64-bit, depending on the vcpu mode) to guest
+memory.
+
+struct kvm_xen_hvm_config {
+       __u32 flags;
+       __u32 msr;
+       __u64 blob_addr_32;
+       __u64 blob_addr_64;
+       __u8 blob_size_32;
+       __u8 blob_size_64;
+       __u8 pad2[30];
+};
+
+
+4.29 KVM_GET_CLOCK
+
+Capability: KVM_CAP_ADJUST_CLOCK
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_clock_data (out)
+Returns: 0 on success, -1 on error
+
+Gets the current timestamp of kvmclock as seen by the current guest. In
+conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios
+such as migration.
+
+When KVM_CAP_ADJUST_CLOCK is passed to KVM_CHECK_EXTENSION, it returns the
+set of bits that KVM can return in struct kvm_clock_data's flag member.
+
+The only flag defined now is KVM_CLOCK_TSC_STABLE.  If set, the returned
+value is the exact kvmclock value seen by all VCPUs at the instant
+when KVM_GET_CLOCK was called.  If clear, the returned value is simply
+CLOCK_MONOTONIC plus a constant offset; the offset can be modified
+with KVM_SET_CLOCK.  KVM will try to make all VCPUs follow this clock,
+but the exact value read by each VCPU could differ, because the host
+TSC is not stable.
+
+struct kvm_clock_data {
+       __u64 clock;  /* kvmclock current value */
+       __u32 flags;
+       __u32 pad[9];
+};
+
+
+4.30 KVM_SET_CLOCK
+
+Capability: KVM_CAP_ADJUST_CLOCK
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_clock_data (in)
+Returns: 0 on success, -1 on error
+
+Sets the current timestamp of kvmclock to the value specified in its parameter.
+In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios
+such as migration.
+
+struct kvm_clock_data {
+       __u64 clock;  /* kvmclock current value */
+       __u32 flags;
+       __u32 pad[9];
+};
+
+
+4.31 KVM_GET_VCPU_EVENTS
+
+Capability: KVM_CAP_VCPU_EVENTS
+Extended by: KVM_CAP_INTR_SHADOW
+Architectures: x86, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_vcpu_event (out)
+Returns: 0 on success, -1 on error
+
+X86:
+
+Gets currently pending exceptions, interrupts, and NMIs as well as related
+states of the vcpu.
+
+struct kvm_vcpu_events {
+       struct {
+               __u8 injected;
+               __u8 nr;
+               __u8 has_error_code;
+               __u8 pending;
+               __u32 error_code;
+       } exception;
+       struct {
+               __u8 injected;
+               __u8 nr;
+               __u8 soft;
+               __u8 shadow;
+       } interrupt;
+       struct {
+               __u8 injected;
+               __u8 pending;
+               __u8 masked;
+               __u8 pad;
+       } nmi;
+       __u32 sipi_vector;
+       __u32 flags;
+       struct {
+               __u8 smm;
+               __u8 pending;
+               __u8 smm_inside_nmi;
+               __u8 latched_init;
+       } smi;
+       __u8 reserved[27];
+       __u8 exception_has_payload;
+       __u64 exception_payload;
+};
+
+The following bits are defined in the flags field:
+
+- KVM_VCPUEVENT_VALID_SHADOW may be set to signal that
+  interrupt.shadow contains a valid state.
+
+- KVM_VCPUEVENT_VALID_SMM may be set to signal that smi contains a
+  valid state.
+
+- KVM_VCPUEVENT_VALID_PAYLOAD may be set to signal that the
+  exception_has_payload, exception_payload, and exception.pending
+  fields contain a valid state. This bit will be set whenever
+  KVM_CAP_EXCEPTION_PAYLOAD is enabled.
+
+ARM/ARM64:
+
+If the guest accesses a device that is being emulated by the host kernel in
+such a way that a real device would generate a physical SError, KVM may make
+a virtual SError pending for that VCPU. This system error interrupt remains
+pending until the guest takes the exception by unmasking PSTATE.A.
+
+Running the VCPU may cause it to take a pending SError, or make an access that
+causes an SError to become pending. The event's description is only valid while
+the VPCU is not running.
+
+This API provides a way to read and write the pending 'event' state that is not
+visible to the guest. To save, restore or migrate a VCPU the struct representing
+the state can be read then written using this GET/SET API, along with the other
+guest-visible registers. It is not possible to 'cancel' an SError that has been
+made pending.
+
+A device being emulated in user-space may also wish to generate an SError. To do
+this the events structure can be populated by user-space. The current state
+should be read first, to ensure no existing SError is pending. If an existing
+SError is pending, the architecture's 'Multiple SError interrupts' rules should
+be followed. (2.5.3 of DDI0587.a "ARM Reliability, Availability, and
+Serviceability (RAS) Specification").
+
+SError exceptions always have an ESR value. Some CPUs have the ability to
+specify what the virtual SError's ESR value should be. These systems will
+advertise KVM_CAP_ARM_INJECT_SERROR_ESR. In this case exception.has_esr will
+always have a non-zero value when read, and the agent making an SError pending
+should specify the ISS field in the lower 24 bits of exception.serror_esr. If
+the system supports KVM_CAP_ARM_INJECT_SERROR_ESR, but user-space sets the events
+with exception.has_esr as zero, KVM will choose an ESR.
+
+Specifying exception.has_esr on a system that does not support it will return
+-EINVAL. Setting anything other than the lower 24bits of exception.serror_esr
+will return -EINVAL.
+
+struct kvm_vcpu_events {
+       struct {
+               __u8 serror_pending;
+               __u8 serror_has_esr;
+               /* Align it to 8 bytes */
+               __u8 pad[6];
+               __u64 serror_esr;
+       } exception;
+       __u32 reserved[12];
+};
+
+4.32 KVM_SET_VCPU_EVENTS
+
+Capability: KVM_CAP_VCPU_EVENTS
+Extended by: KVM_CAP_INTR_SHADOW
+Architectures: x86, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_vcpu_event (in)
+Returns: 0 on success, -1 on error
+
+X86:
+
+Set pending exceptions, interrupts, and NMIs as well as related states of the
+vcpu.
+
+See KVM_GET_VCPU_EVENTS for the data structure.
+
+Fields that may be modified asynchronously by running VCPUs can be excluded
+from the update. These fields are nmi.pending, sipi_vector, smi.smm,
+smi.pending. Keep the corresponding bits in the flags field cleared to
+suppress overwriting the current in-kernel state. The bits are:
+
+KVM_VCPUEVENT_VALID_NMI_PENDING - transfer nmi.pending to the kernel
+KVM_VCPUEVENT_VALID_SIPI_VECTOR - transfer sipi_vector
+KVM_VCPUEVENT_VALID_SMM         - transfer the smi sub-struct.
+
+If KVM_CAP_INTR_SHADOW is available, KVM_VCPUEVENT_VALID_SHADOW can be set in
+the flags field to signal that interrupt.shadow contains a valid state and
+shall be written into the VCPU.
+
+KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available.
+
+If KVM_CAP_EXCEPTION_PAYLOAD is enabled, KVM_VCPUEVENT_VALID_PAYLOAD
+can be set in the flags field to signal that the
+exception_has_payload, exception_payload, and exception.pending fields
+contain a valid state and shall be written into the VCPU.
+
+ARM/ARM64:
+
+Set the pending SError exception state for this VCPU. It is not possible to
+'cancel' an Serror that has been made pending.
+
+See KVM_GET_VCPU_EVENTS for the data structure.
+
+
+4.33 KVM_GET_DEBUGREGS
+
+Capability: KVM_CAP_DEBUGREGS
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_debugregs (out)
+Returns: 0 on success, -1 on error
+
+Reads debug registers from the vcpu.
+
+struct kvm_debugregs {
+       __u64 db[4];
+       __u64 dr6;
+       __u64 dr7;
+       __u64 flags;
+       __u64 reserved[9];
+};
+
+
+4.34 KVM_SET_DEBUGREGS
+
+Capability: KVM_CAP_DEBUGREGS
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_debugregs (in)
+Returns: 0 on success, -1 on error
+
+Writes debug registers into the vcpu.
+
+See KVM_GET_DEBUGREGS for the data structure. The flags field is unused
+yet and must be cleared on entry.
+
+
+4.35 KVM_SET_USER_MEMORY_REGION
+
+Capability: KVM_CAP_USER_MEMORY
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_userspace_memory_region (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_userspace_memory_region {
+       __u32 slot;
+       __u32 flags;
+       __u64 guest_phys_addr;
+       __u64 memory_size; /* bytes */
+       __u64 userspace_addr; /* start of the userspace allocated memory */
+};
+
+/* for kvm_memory_region::flags */
+#define KVM_MEM_LOG_DIRTY_PAGES        (1UL << 0)
+#define KVM_MEM_READONLY       (1UL << 1)
+
+This ioctl allows the user to create, modify or delete a guest physical
+memory slot.  Bits 0-15 of "slot" specify the slot id and this value
+should be less than the maximum number of user memory slots supported per
+VM.  The maximum allowed slots can be queried using KVM_CAP_NR_MEMSLOTS.
+Slots may not overlap in guest physical address space.
+
+If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 of "slot"
+specifies the address space which is being modified.  They must be
+less than the value that KVM_CHECK_EXTENSION returns for the
+KVM_CAP_MULTI_ADDRESS_SPACE capability.  Slots in separate address spaces
+are unrelated; the restriction on overlapping slots only applies within
+each address space.
+
+Deleting a slot is done by passing zero for memory_size.  When changing
+an existing slot, it may be moved in the guest physical memory space,
+or its flags may be modified, but it may not be resized.
+
+Memory for the region is taken starting at the address denoted by the
+field userspace_addr, which must point at user addressable memory for
+the entire memory slot size.  Any object may back this memory, including
+anonymous memory, ordinary files, and hugetlbfs.
+
+It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
+be identical.  This allows large pages in the guest to be backed by large
+pages in the host.
+
+The flags field supports two flags: KVM_MEM_LOG_DIRTY_PAGES and
+KVM_MEM_READONLY.  The former can be set to instruct KVM to keep track of
+writes to memory within the slot.  See KVM_GET_DIRTY_LOG ioctl to know how to
+use it.  The latter can be set, if KVM_CAP_READONLY_MEM capability allows it,
+to make a new slot read-only.  In this case, writes to this memory will be
+posted to userspace as KVM_EXIT_MMIO exits.
+
+When the KVM_CAP_SYNC_MMU capability is available, changes in the backing of
+the memory region are automatically reflected into the guest.  For example, an
+mmap() that affects the region will be made visible immediately.  Another
+example is madvise(MADV_DROP).
+
+It is recommended to use this API instead of the KVM_SET_MEMORY_REGION ioctl.
+The KVM_SET_MEMORY_REGION does not allow fine grained control over memory
+allocation and is deprecated.
+
+
+4.36 KVM_SET_TSS_ADDR
+
+Capability: KVM_CAP_SET_TSS_ADDR
+Architectures: x86
+Type: vm ioctl
+Parameters: unsigned long tss_address (in)
+Returns: 0 on success, -1 on error
+
+This ioctl defines the physical address of a three-page region in the guest
+physical address space.  The region must be within the first 4GB of the
+guest physical address space and must not conflict with any memory slot
+or any mmio address.  The guest may malfunction if it accesses this memory
+region.
+
+This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
+because of a quirk in the virtualization implementation (see the internals
+documentation when it pops into existence).
+
+
+4.37 KVM_ENABLE_CAP
+
+Capability: KVM_CAP_ENABLE_CAP
+Architectures: mips, ppc, s390
+Type: vcpu ioctl
+Parameters: struct kvm_enable_cap (in)
+Returns: 0 on success; -1 on error
+
+Capability: KVM_CAP_ENABLE_CAP_VM
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_enable_cap (in)
+Returns: 0 on success; -1 on error
+
++Not all extensions are enabled by default. Using this ioctl the application
+can enable an extension, making it available to the guest.
+
+On systems that do not support this ioctl, it always fails. On systems that
+do support it, it only works for extensions that are supported for enablement.
+
+To check if a capability can be enabled, the KVM_CHECK_EXTENSION ioctl should
+be used.
+
+struct kvm_enable_cap {
+       /* in */
+       __u32 cap;
+
+The capability that is supposed to get enabled.
+
+       __u32 flags;
+
+A bitfield indicating future enhancements. Has to be 0 for now.
+
+       __u64 args[4];
+
+Arguments for enabling a feature. If a feature needs initial values to
+function properly, this is the place to put them.
+
+       __u8  pad[64];
+};
+
+The vcpu ioctl should be used for vcpu-specific capabilities, the vm ioctl
+for vm-wide capabilities.
+
+4.38 KVM_GET_MP_STATE
+
+Capability: KVM_CAP_MP_STATE
+Architectures: x86, s390, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_mp_state (out)
+Returns: 0 on success; -1 on error
+
+struct kvm_mp_state {
+       __u32 mp_state;
+};
+
+Returns the vcpu's current "multiprocessing state" (though also valid on
+uniprocessor guests).
+
+Possible values are:
+
+ - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running [x86,arm/arm64]
+ - KVM_MP_STATE_UNINITIALIZED:   the vcpu is an application processor (AP)
+                                 which has not yet received an INIT signal [x86]
+ - KVM_MP_STATE_INIT_RECEIVED:   the vcpu has received an INIT signal, and is
+                                 now ready for a SIPI [x86]
+ - KVM_MP_STATE_HALTED:          the vcpu has executed a HLT instruction and
+                                 is waiting for an interrupt [x86]
+ - KVM_MP_STATE_SIPI_RECEIVED:   the vcpu has just received a SIPI (vector
+                                 accessible via KVM_GET_VCPU_EVENTS) [x86]
+ - KVM_MP_STATE_STOPPED:         the vcpu is stopped [s390,arm/arm64]
+ - KVM_MP_STATE_CHECK_STOP:      the vcpu is in a special error state [s390]
+ - KVM_MP_STATE_OPERATING:       the vcpu is operating (running or halted)
+                                 [s390]
+ - KVM_MP_STATE_LOAD:            the vcpu is in a special load/startup state
+                                 [s390]
+
+On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
+
+For arm/arm64:
+
+The only states that are valid are KVM_MP_STATE_STOPPED and
+KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.
+
+4.39 KVM_SET_MP_STATE
+
+Capability: KVM_CAP_MP_STATE
+Architectures: x86, s390, arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_mp_state (in)
+Returns: 0 on success; -1 on error
+
+Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for
+arguments.
+
+On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
+in-kernel irqchip, the multiprocessing state must be maintained by userspace on
+these architectures.
+
+For arm/arm64:
+
+The only states that are valid are KVM_MP_STATE_STOPPED and
+KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.
+
+4.40 KVM_SET_IDENTITY_MAP_ADDR
+
+Capability: KVM_CAP_SET_IDENTITY_MAP_ADDR
+Architectures: x86
+Type: vm ioctl
+Parameters: unsigned long identity (in)
+Returns: 0 on success, -1 on error
+
+This ioctl defines the physical address of a one-page region in the guest
+physical address space.  The region must be within the first 4GB of the
+guest physical address space and must not conflict with any memory slot
+or any mmio address.  The guest may malfunction if it accesses this memory
+region.
+
+Setting the address to 0 will result in resetting the address to its default
+(0xfffbc000).
+
+This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
+because of a quirk in the virtualization implementation (see the internals
+documentation when it pops into existence).
+
+Fails if any VCPU has already been created.
+
+4.41 KVM_SET_BOOT_CPU_ID
+
+Capability: KVM_CAP_SET_BOOT_CPU_ID
+Architectures: x86
+Type: vm ioctl
+Parameters: unsigned long vcpu_id
+Returns: 0 on success, -1 on error
+
+Define which vcpu is the Bootstrap Processor (BSP).  Values are the same
+as the vcpu id in KVM_CREATE_VCPU.  If this ioctl is not called, the default
+is vcpu 0.
+
+
+4.42 KVM_GET_XSAVE
+
+Capability: KVM_CAP_XSAVE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xsave (out)
+Returns: 0 on success, -1 on error
+
+struct kvm_xsave {
+       __u32 region[1024];
+};
+
+This ioctl would copy current vcpu's xsave struct to the userspace.
+
+
+4.43 KVM_SET_XSAVE
+
+Capability: KVM_CAP_XSAVE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xsave (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_xsave {
+       __u32 region[1024];
+};
+
+This ioctl would copy userspace's xsave struct to the kernel.
+
+
+4.44 KVM_GET_XCRS
+
+Capability: KVM_CAP_XCRS
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xcrs (out)
+Returns: 0 on success, -1 on error
+
+struct kvm_xcr {
+       __u32 xcr;
+       __u32 reserved;
+       __u64 value;
+};
+
+struct kvm_xcrs {
+       __u32 nr_xcrs;
+       __u32 flags;
+       struct kvm_xcr xcrs[KVM_MAX_XCRS];
+       __u64 padding[16];
+};
+
+This ioctl would copy current vcpu's xcrs to the userspace.
+
+
+4.45 KVM_SET_XCRS
+
+Capability: KVM_CAP_XCRS
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_xcrs (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_xcr {
+       __u32 xcr;
+       __u32 reserved;
+       __u64 value;
+};
+
+struct kvm_xcrs {
+       __u32 nr_xcrs;
+       __u32 flags;
+       struct kvm_xcr xcrs[KVM_MAX_XCRS];
+       __u64 padding[16];
+};
+
+This ioctl would set vcpu's xcr to the value userspace specified.
+
+
+4.46 KVM_GET_SUPPORTED_CPUID
+
+Capability: KVM_CAP_EXT_CPUID
+Architectures: x86
+Type: system ioctl
+Parameters: struct kvm_cpuid2 (in/out)
+Returns: 0 on success, -1 on error
+
+struct kvm_cpuid2 {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry2 entries[0];
+};
+
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
+
+struct kvm_cpuid_entry2 {
+       __u32 function;
+       __u32 index;
+       __u32 flags;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding[3];
+};
+
+This ioctl returns x86 cpuid features which are supported by both the
+hardware and kvm in its default configuration.  Userspace can use the
+information returned by this ioctl to construct cpuid information (for
+KVM_SET_CPUID2) that is consistent with hardware, kernel, and
+userspace capabilities, and with user requirements (for example, the
+user may wish to constrain cpuid to emulate older hardware, or for
+feature consistency across a cluster).
+
+Note that certain capabilities, such as KVM_CAP_X86_DISABLE_EXITS, may
+expose cpuid features (e.g. MONITOR) which are not supported by kvm in
+its default configuration. If userspace enables such capabilities, it
+is responsible for modifying the results of this ioctl appropriately.
+
+Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
+with the 'nent' field indicating the number of entries in the variable-size
+array 'entries'.  If the number of entries is too low to describe the cpu
+capabilities, an error (E2BIG) is returned.  If the number is too high,
+the 'nent' field is adjusted and an error (ENOMEM) is returned.  If the
+number is just right, the 'nent' field is adjusted to the number of valid
+entries in the 'entries' array, which is then filled.
+
+The entries returned are the host cpuid as returned by the cpuid instruction,
+with unknown or unsupported features masked out.  Some features (for example,
+x2apic), may not be present in the host cpu, but are exposed by kvm if it can
+emulate them efficiently. The fields in each entry are defined as follows:
+
+  function: the eax value used to obtain the entry
+  index: the ecx value used to obtain the entry (for entries that are
+         affected by ecx)
+  flags: an OR of zero or more of the following:
+        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
+           if the index field is valid
+        KVM_CPUID_FLAG_STATEFUL_FUNC:
+           if cpuid for this function returns different values for successive
+           invocations; there will be several entries with the same function,
+           all with this flag set
+        KVM_CPUID_FLAG_STATE_READ_NEXT:
+           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
+           the first entry to be read by a cpu
+   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
+         this function/index combination
+
+The TSC deadline timer feature (CPUID leaf 1, ecx[24]) is always returned
+as false, since the feature depends on KVM_CREATE_IRQCHIP for local APIC
+support.  Instead it is reported via
+
+  ioctl(KVM_CHECK_EXTENSION, KVM_CAP_TSC_DEADLINE_TIMER)
+
+if that returns true and you use KVM_CREATE_IRQCHIP, or if you emulate the
+feature in userspace, then you can enable the feature for KVM_SET_CPUID2.
+
+
+4.47 KVM_PPC_GET_PVINFO
+
+Capability: KVM_CAP_PPC_GET_PVINFO
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_ppc_pvinfo (out)
+Returns: 0 on success, !0 on error
+
+struct kvm_ppc_pvinfo {
+       __u32 flags;
+       __u32 hcall[4];
+       __u8  pad[108];
+};
+
+This ioctl fetches PV specific information that need to be passed to the guest
+using the device tree or other means from vm context.
+
+The hcall array defines 4 instructions that make up a hypercall.
+
+If any additional field gets added to this structure later on, a bit for that
+additional piece of information will be set in the flags bitmap.
+
+The flags bitmap is defined as:
+
+   /* the host supports the ePAPR idle hcall
+   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
+
+4.52 KVM_SET_GSI_ROUTING
+
+Capability: KVM_CAP_IRQ_ROUTING
+Architectures: x86 s390 arm arm64
+Type: vm ioctl
+Parameters: struct kvm_irq_routing (in)
+Returns: 0 on success, -1 on error
+
+Sets the GSI routing table entries, overwriting any previously set entries.
+
+On arm/arm64, GSI routing has the following limitation:
+- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
+
+struct kvm_irq_routing {
+       __u32 nr;
+       __u32 flags;
+       struct kvm_irq_routing_entry entries[0];
+};
+
+No flags are specified so far, the corresponding field must be set to zero.
+
+struct kvm_irq_routing_entry {
+       __u32 gsi;
+       __u32 type;
+       __u32 flags;
+       __u32 pad;
+       union {
+               struct kvm_irq_routing_irqchip irqchip;
+               struct kvm_irq_routing_msi msi;
+               struct kvm_irq_routing_s390_adapter adapter;
+               struct kvm_irq_routing_hv_sint hv_sint;
+               __u32 pad[8];
+       } u;
+};
+
+/* gsi routing entry types */
+#define KVM_IRQ_ROUTING_IRQCHIP 1
+#define KVM_IRQ_ROUTING_MSI 2
+#define KVM_IRQ_ROUTING_S390_ADAPTER 3
+#define KVM_IRQ_ROUTING_HV_SINT 4
+
+flags:
+- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI routing entry
+  type, specifies that the devid field contains a valid value.  The per-VM
+  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
+  the device ID.  If this capability is not available, userspace should
+  never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
+- zero otherwise
+
+struct kvm_irq_routing_irqchip {
+       __u32 irqchip;
+       __u32 pin;
+};
+
+struct kvm_irq_routing_msi {
+       __u32 address_lo;
+       __u32 address_hi;
+       __u32 data;
+       union {
+               __u32 pad;
+               __u32 devid;
+       };
+};
+
+If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
+for the device that wrote the MSI message.  For PCI, this is usually a
+BFD identifier in the lower 16 bits.
+
+On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
+feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
+address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
+address_hi must be zero.
+
+struct kvm_irq_routing_s390_adapter {
+       __u64 ind_addr;
+       __u64 summary_addr;
+       __u64 ind_offset;
+       __u32 summary_offset;
+       __u32 adapter_id;
+};
+
+struct kvm_irq_routing_hv_sint {
+       __u32 vcpu;
+       __u32 sint;
+};
+
+
+4.55 KVM_SET_TSC_KHZ
+
+Capability: KVM_CAP_TSC_CONTROL
+Architectures: x86
+Type: vcpu ioctl
+Parameters: virtual tsc_khz
+Returns: 0 on success, -1 on error
+
+Specifies the tsc frequency for the virtual machine. The unit of the
+frequency is KHz.
+
+
+4.56 KVM_GET_TSC_KHZ
+
+Capability: KVM_CAP_GET_TSC_KHZ
+Architectures: x86
+Type: vcpu ioctl
+Parameters: none
+Returns: virtual tsc-khz on success, negative value on error
+
+Returns the tsc frequency of the guest. The unit of the return value is
+KHz. If the host has unstable tsc this ioctl returns -EIO instead as an
+error.
+
+
+4.57 KVM_GET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (out)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+       char regs[KVM_APIC_REG_SIZE];
+};
+
+Reads the Local APIC registers and copies them into the input argument.  The
+data format and layout are the same as documented in the architecture manual.
+
+If KVM_X2APIC_API_USE_32BIT_IDS feature of KVM_CAP_X2APIC_API is
+enabled, then the format of APIC_ID register depends on the APIC mode
+(reported by MSR_IA32_APICBASE) of its VCPU.  x2APIC stores APIC ID in
+the APIC_ID register (bytes 32-35).  xAPIC only allows an 8-bit APIC ID
+which is stored in bits 31-24 of the APIC register, or equivalently in
+byte 35 of struct kvm_lapic_state's regs field.  KVM_GET_LAPIC must then
+be called after MSR_IA32_APICBASE has been set with KVM_SET_MSR.
+
+If KVM_X2APIC_API_USE_32BIT_IDS feature is disabled, struct kvm_lapic_state
+always uses xAPIC format.
+
+
+4.58 KVM_SET_LAPIC
+
+Capability: KVM_CAP_IRQCHIP
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_lapic_state (in)
+Returns: 0 on success, -1 on error
+
+#define KVM_APIC_REG_SIZE 0x400
+struct kvm_lapic_state {
+       char regs[KVM_APIC_REG_SIZE];
+};
+
+Copies the input argument into the Local APIC registers.  The data format
+and layout are the same as documented in the architecture manual.
+
+The format of the APIC ID register (bytes 32-35 of struct kvm_lapic_state's
+regs field) depends on the state of the KVM_CAP_X2APIC_API capability.
+See the note in KVM_GET_LAPIC.
+
+
+4.59 KVM_IOEVENTFD
+
+Capability: KVM_CAP_IOEVENTFD
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_ioeventfd (in)
+Returns: 0 on success, !0 on error
+
+This ioctl attaches or detaches an ioeventfd to a legal pio/mmio address
+within the guest.  A guest write in the registered address will signal the
+provided event instead of triggering an exit.
+
+struct kvm_ioeventfd {
+       __u64 datamatch;
+       __u64 addr;        /* legal pio/mmio address */
+       __u32 len;         /* 0, 1, 2, 4, or 8 bytes    */
+       __s32 fd;
+       __u32 flags;
+       __u8  pad[36];
+};
+
+For the special case of virtio-ccw devices on s390, the ioevent is matched
+to a subchannel/virtqueue tuple instead.
+
+The following flags are defined:
+
+#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
+#define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
+#define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
+#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
+       (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
+
+If datamatch flag is set, the event will be signaled only if the written value
+to the registered address is equal to datamatch in struct kvm_ioeventfd.
+
+For virtio-ccw devices, addr contains the subchannel id and datamatch the
+virtqueue index.
+
+With KVM_CAP_IOEVENTFD_ANY_LENGTH, a zero length ioeventfd is allowed, and
+the kernel will ignore the length of guest write and may get a faster vmexit.
+The speedup may only apply to specific architectures, but the ioeventfd will
+work anyway.
+
+4.60 KVM_DIRTY_TLB
+
+Capability: KVM_CAP_SW_TLB
+Architectures: ppc
+Type: vcpu ioctl
+Parameters: struct kvm_dirty_tlb (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_dirty_tlb {
+       __u64 bitmap;
+       __u32 num_dirty;
+};
+
+This must be called whenever userspace has changed an entry in the shared
+TLB, prior to calling KVM_RUN on the associated vcpu.
+
+The "bitmap" field is the userspace address of an array.  This array
+consists of a number of bits, equal to the total number of TLB entries as
+determined by the last successful call to KVM_CONFIG_TLB, rounded up to the
+nearest multiple of 64.
+
+Each bit corresponds to one TLB entry, ordered the same as in the shared TLB
+array.
+
+The array is little-endian: the bit 0 is the least significant bit of the
+first byte, bit 8 is the least significant bit of the second byte, etc.
+This avoids any complications with differing word sizes.
+
+The "num_dirty" field is a performance hint for KVM to determine whether it
+should skip processing the bitmap and just invalidate everything.  It must
+be set to the number of set bits in the bitmap.
+
+
+4.62 KVM_CREATE_SPAPR_TCE
+
+Capability: KVM_CAP_SPAPR_TCE
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_create_spapr_tce (in)
+Returns: file descriptor for manipulating the created TCE table
+
+This creates a virtual TCE (translation control entry) table, which
+is an IOMMU for PAPR-style virtual I/O.  It is used to translate
+logical addresses used in virtual I/O into guest physical addresses,
+and provides a scatter/gather capability for PAPR virtual I/O.
+
+/* for KVM_CAP_SPAPR_TCE */
+struct kvm_create_spapr_tce {
+       __u64 liobn;
+       __u32 window_size;
+};
+
+The liobn field gives the logical IO bus number for which to create a
+TCE table.  The window_size field specifies the size of the DMA window
+which this TCE table will translate - the table will contain one 64
+bit TCE entry for every 4kiB of the DMA window.
+
+When the guest issues an H_PUT_TCE hcall on a liobn for which a TCE
+table has been created using this ioctl(), the kernel will handle it
+in real mode, updating the TCE table.  H_PUT_TCE calls for other
+liobns will cause a vm exit and must be handled by userspace.
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the created TCE table into userspace.  This lets userspace read
+the entries written by kernel-handled H_PUT_TCE calls, and also lets
+userspace update the TCE table directly which is useful in some
+circumstances.
+
+
+4.63 KVM_ALLOCATE_RMA
+
+Capability: KVM_CAP_PPC_RMA
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_allocate_rma (out)
+Returns: file descriptor for mapping the allocated RMA
+
+This allocates a Real Mode Area (RMA) from the pool allocated at boot
+time by the kernel.  An RMA is a physically-contiguous, aligned region
+of memory used on older POWER processors to provide the memory which
+will be accessed by real-mode (MMU off) accesses in a KVM guest.
+POWER processors support a set of sizes for the RMA that usually
+includes 64MB, 128MB, 256MB and some larger powers of two.
+
+/* for KVM_ALLOCATE_RMA */
+struct kvm_allocate_rma {
+       __u64 rma_size;
+};
+
+The return value is a file descriptor which can be passed to mmap(2)
+to map the allocated RMA into userspace.  The mapped area can then be
+passed to the KVM_SET_USER_MEMORY_REGION ioctl to establish it as the
+RMA for a virtual machine.  The size of the RMA in bytes (which is
+fixed at host kernel boot time) is returned in the rma_size field of
+the argument structure.
+
+The KVM_CAP_PPC_RMA capability is 1 or 2 if the KVM_ALLOCATE_RMA ioctl
+is supported; 2 if the processor requires all virtual machines to have
+an RMA, or 1 if the processor can use an RMA but doesn't require it,
+because it supports the Virtual RMA (VRMA) facility.
+
+
+4.64 KVM_NMI
+
+Capability: KVM_CAP_USER_NMI
+Architectures: x86
+Type: vcpu ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+
+Queues an NMI on the thread's vcpu.  Note this is well defined only
+when KVM_CREATE_IRQCHIP has not been called, since this is an interface
+between the virtual cpu core and virtual local APIC.  After KVM_CREATE_IRQCHIP
+has been called, this interface is completely emulated within the kernel.
+
+To use this to emulate the LINT1 input with KVM_CREATE_IRQCHIP, use the
+following algorithm:
+
+  - pause the vcpu
+  - read the local APIC's state (KVM_GET_LAPIC)
+  - check whether changing LINT1 will queue an NMI (see the LVT entry for LINT1)
+  - if so, issue KVM_NMI
+  - resume the vcpu
+
+Some guests configure the LINT1 NMI input to cause a panic, aiding in
+debugging.
+
+
+4.65 KVM_S390_UCAS_MAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl maps the memory at "user_addr" with the length "length" to
+the vcpu's address space starting at "vcpu_addr". All parameters need to
+be aligned by 1 megabyte.
+
+
+4.66 KVM_S390_UCAS_UNMAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl unmaps the memory in the vcpu's address space starting at
+"vcpu_addr" with the length "length". The field "user_addr" is ignored.
+All parameters need to be aligned by 1 megabyte.
+
+
+4.67 KVM_S390_VCPU_FAULT
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: vcpu absolute address (in)
+Returns: 0 in case of success
+
+This call creates a page table entry on the virtual cpu's address space
+(for user controlled virtual machines) or the virtual machine's address
+space (for regular virtual machines). This only works for minor faults,
+thus it's recommended to access subject memory page via the user page
+table upfront. This is useful to handle validity intercepts for user
+controlled virtual machines to fault in the virtual cpu's lowcore pages
+prior to calling the KVM_RUN ioctl.
+
+
+4.68 KVM_SET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in)
+Returns: 0 on success, negative value on failure
+Errors:
+  ENOENT:   no such register
+  EINVAL:   invalid register ID, or no such register
+  EPERM:    (arm64) register access not allowed before vcpu finalization
+(These error codes are indicative only: do not rely on a specific error
+code being returned in a specific situation.)
+
+struct kvm_one_reg {
+       __u64 id;
+       __u64 addr;
+};
+
+Using this ioctl, a single vcpu register can be set to a specific value
+defined by user space with the passed in struct kvm_one_reg, where id
+refers to the register identifier as described below and addr is a pointer
+to a variable with the respective size. There can be architecture agnostic
+and architecture specific registers. Each have their own range of operation
+and their own constants and width. To keep track of the implemented
+registers, find a list below:
+
+  Arch  |           Register            | Width (bits)
+        |                               |
+  PPC   | KVM_REG_PPC_HIOR              | 64
+  PPC   | KVM_REG_PPC_IAC1              | 64
+  PPC   | KVM_REG_PPC_IAC2              | 64
+  PPC   | KVM_REG_PPC_IAC3              | 64
+  PPC   | KVM_REG_PPC_IAC4              | 64
+  PPC   | KVM_REG_PPC_DAC1              | 64
+  PPC   | KVM_REG_PPC_DAC2              | 64
+  PPC   | KVM_REG_PPC_DABR              | 64
+  PPC   | KVM_REG_PPC_DSCR              | 64
+  PPC   | KVM_REG_PPC_PURR              | 64
+  PPC   | KVM_REG_PPC_SPURR             | 64
+  PPC   | KVM_REG_PPC_DAR               | 64
+  PPC   | KVM_REG_PPC_DSISR             | 32
+  PPC   | KVM_REG_PPC_AMR               | 64
+  PPC   | KVM_REG_PPC_UAMOR             | 64
+  PPC   | KVM_REG_PPC_MMCR0             | 64
+  PPC   | KVM_REG_PPC_MMCR1             | 64
+  PPC   | KVM_REG_PPC_MMCRA             | 64
+  PPC   | KVM_REG_PPC_MMCR2             | 64
+  PPC   | KVM_REG_PPC_MMCRS             | 64
+  PPC   | KVM_REG_PPC_SIAR              | 64
+  PPC   | KVM_REG_PPC_SDAR              | 64
+  PPC   | KVM_REG_PPC_SIER              | 64
+  PPC   | KVM_REG_PPC_PMC1              | 32
+  PPC   | KVM_REG_PPC_PMC2              | 32
+  PPC   | KVM_REG_PPC_PMC3              | 32
+  PPC   | KVM_REG_PPC_PMC4              | 32
+  PPC   | KVM_REG_PPC_PMC5              | 32
+  PPC   | KVM_REG_PPC_PMC6              | 32
+  PPC   | KVM_REG_PPC_PMC7              | 32
+  PPC   | KVM_REG_PPC_PMC8              | 32
+  PPC   | KVM_REG_PPC_FPR0              | 64
+          ...
+  PPC   | KVM_REG_PPC_FPR31             | 64
+  PPC   | KVM_REG_PPC_VR0               | 128
+          ...
+  PPC   | KVM_REG_PPC_VR31              | 128
+  PPC   | KVM_REG_PPC_VSR0              | 128
+          ...
+  PPC   | KVM_REG_PPC_VSR31             | 128
+  PPC   | KVM_REG_PPC_FPSCR             | 64
+  PPC   | KVM_REG_PPC_VSCR              | 32
+  PPC   | KVM_REG_PPC_VPA_ADDR          | 64
+  PPC   | KVM_REG_PPC_VPA_SLB           | 128
+  PPC   | KVM_REG_PPC_VPA_DTL           | 128
+  PPC   | KVM_REG_PPC_EPCR              | 32
+  PPC   | KVM_REG_PPC_EPR               | 32
+  PPC   | KVM_REG_PPC_TCR               | 32
+  PPC   | KVM_REG_PPC_TSR               | 32
+  PPC   | KVM_REG_PPC_OR_TSR            | 32
+  PPC   | KVM_REG_PPC_CLEAR_TSR         | 32
+  PPC   | KVM_REG_PPC_MAS0              | 32
+  PPC   | KVM_REG_PPC_MAS1              | 32
+  PPC   | KVM_REG_PPC_MAS2              | 64
+  PPC   | KVM_REG_PPC_MAS7_3            | 64
+  PPC   | KVM_REG_PPC_MAS4              | 32
+  PPC   | KVM_REG_PPC_MAS6              | 32
+  PPC   | KVM_REG_PPC_MMUCFG            | 32
+  PPC   | KVM_REG_PPC_TLB0CFG           | 32
+  PPC   | KVM_REG_PPC_TLB1CFG           | 32
+  PPC   | KVM_REG_PPC_TLB2CFG           | 32
+  PPC   | KVM_REG_PPC_TLB3CFG           | 32
+  PPC   | KVM_REG_PPC_TLB0PS            | 32
+  PPC   | KVM_REG_PPC_TLB1PS            | 32
+  PPC   | KVM_REG_PPC_TLB2PS            | 32
+  PPC   | KVM_REG_PPC_TLB3PS            | 32
+  PPC   | KVM_REG_PPC_EPTCFG            | 32
+  PPC   | KVM_REG_PPC_ICP_STATE         | 64
+  PPC   | KVM_REG_PPC_VP_STATE          | 128
+  PPC   | KVM_REG_PPC_TB_OFFSET         | 64
+  PPC   | KVM_REG_PPC_SPMC1             | 32
+  PPC   | KVM_REG_PPC_SPMC2             | 32
+  PPC   | KVM_REG_PPC_IAMR              | 64
+  PPC   | KVM_REG_PPC_TFHAR             | 64
+  PPC   | KVM_REG_PPC_TFIAR             | 64
+  PPC   | KVM_REG_PPC_TEXASR            | 64
+  PPC   | KVM_REG_PPC_FSCR              | 64
+  PPC   | KVM_REG_PPC_PSPB              | 32
+  PPC   | KVM_REG_PPC_EBBHR             | 64
+  PPC   | KVM_REG_PPC_EBBRR             | 64
+  PPC   | KVM_REG_PPC_BESCR             | 64
+  PPC   | KVM_REG_PPC_TAR               | 64
+  PPC   | KVM_REG_PPC_DPDES             | 64
+  PPC   | KVM_REG_PPC_DAWR              | 64
+  PPC   | KVM_REG_PPC_DAWRX             | 64
+  PPC   | KVM_REG_PPC_CIABR             | 64
+  PPC   | KVM_REG_PPC_IC                | 64
+  PPC   | KVM_REG_PPC_VTB               | 64
+  PPC   | KVM_REG_PPC_CSIGR             | 64
+  PPC   | KVM_REG_PPC_TACR              | 64
+  PPC   | KVM_REG_PPC_TCSCR             | 64
+  PPC   | KVM_REG_PPC_PID               | 64
+  PPC   | KVM_REG_PPC_ACOP              | 64
+  PPC   | KVM_REG_PPC_VRSAVE            | 32
+  PPC   | KVM_REG_PPC_LPCR              | 32
+  PPC   | KVM_REG_PPC_LPCR_64           | 64
+  PPC   | KVM_REG_PPC_PPR               | 64
+  PPC   | KVM_REG_PPC_ARCH_COMPAT       | 32
+  PPC   | KVM_REG_PPC_DABRX             | 32
+  PPC   | KVM_REG_PPC_WORT              | 64
+  PPC  | KVM_REG_PPC_SPRG9             | 64
+  PPC  | KVM_REG_PPC_DBSR              | 32
+  PPC   | KVM_REG_PPC_TIDR              | 64
+  PPC   | KVM_REG_PPC_PSSCR             | 64
+  PPC   | KVM_REG_PPC_DEC_EXPIRY        | 64
+  PPC   | KVM_REG_PPC_PTCR              | 64
+  PPC   | KVM_REG_PPC_TM_GPR0           | 64
+          ...
+  PPC   | KVM_REG_PPC_TM_GPR31          | 64
+  PPC   | KVM_REG_PPC_TM_VSR0           | 128
+          ...
+  PPC   | KVM_REG_PPC_TM_VSR63          | 128
+  PPC   | KVM_REG_PPC_TM_CR             | 64
+  PPC   | KVM_REG_PPC_TM_LR             | 64
+  PPC   | KVM_REG_PPC_TM_CTR            | 64
+  PPC   | KVM_REG_PPC_TM_FPSCR          | 64
+  PPC   | KVM_REG_PPC_TM_AMR            | 64
+  PPC   | KVM_REG_PPC_TM_PPR            | 64
+  PPC   | KVM_REG_PPC_TM_VRSAVE         | 64
+  PPC   | KVM_REG_PPC_TM_VSCR           | 32
+  PPC   | KVM_REG_PPC_TM_DSCR           | 64
+  PPC   | KVM_REG_PPC_TM_TAR            | 64
+  PPC   | KVM_REG_PPC_TM_XER            | 64
+        |                               |
+  MIPS  | KVM_REG_MIPS_R0               | 64
+          ...
+  MIPS  | KVM_REG_MIPS_R31              | 64
+  MIPS  | KVM_REG_MIPS_HI               | 64
+  MIPS  | KVM_REG_MIPS_LO               | 64
+  MIPS  | KVM_REG_MIPS_PC               | 64
+  MIPS  | KVM_REG_MIPS_CP0_INDEX        | 32
+  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO0     | 64
+  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO1     | 64
+  MIPS  | KVM_REG_MIPS_CP0_CONTEXT      | 64
+  MIPS  | KVM_REG_MIPS_CP0_CONTEXTCONFIG| 32
+  MIPS  | KVM_REG_MIPS_CP0_USERLOCAL    | 64
+  MIPS  | KVM_REG_MIPS_CP0_XCONTEXTCONFIG| 64
+  MIPS  | KVM_REG_MIPS_CP0_PAGEMASK     | 32
+  MIPS  | KVM_REG_MIPS_CP0_PAGEGRAIN    | 32
+  MIPS  | KVM_REG_MIPS_CP0_SEGCTL0      | 64
+  MIPS  | KVM_REG_MIPS_CP0_SEGCTL1      | 64
+  MIPS  | KVM_REG_MIPS_CP0_SEGCTL2      | 64
+  MIPS  | KVM_REG_MIPS_CP0_PWBASE       | 64
+  MIPS  | KVM_REG_MIPS_CP0_PWFIELD      | 64
+  MIPS  | KVM_REG_MIPS_CP0_PWSIZE       | 64
+  MIPS  | KVM_REG_MIPS_CP0_WIRED        | 32
+  MIPS  | KVM_REG_MIPS_CP0_PWCTL        | 32
+  MIPS  | KVM_REG_MIPS_CP0_HWRENA       | 32
+  MIPS  | KVM_REG_MIPS_CP0_BADVADDR     | 64
+  MIPS  | KVM_REG_MIPS_CP0_BADINSTR     | 32
+  MIPS  | KVM_REG_MIPS_CP0_BADINSTRP    | 32
+  MIPS  | KVM_REG_MIPS_CP0_COUNT        | 32
+  MIPS  | KVM_REG_MIPS_CP0_ENTRYHI      | 64
+  MIPS  | KVM_REG_MIPS_CP0_COMPARE      | 32
+  MIPS  | KVM_REG_MIPS_CP0_STATUS       | 32
+  MIPS  | KVM_REG_MIPS_CP0_INTCTL       | 32
+  MIPS  | KVM_REG_MIPS_CP0_CAUSE        | 32
+  MIPS  | KVM_REG_MIPS_CP0_EPC          | 64
+  MIPS  | KVM_REG_MIPS_CP0_PRID         | 32
+  MIPS  | KVM_REG_MIPS_CP0_EBASE        | 64
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG       | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG1      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG2      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG3      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG4      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG5      | 32
+  MIPS  | KVM_REG_MIPS_CP0_CONFIG7      | 32
+  MIPS  | KVM_REG_MIPS_CP0_XCONTEXT     | 64
+  MIPS  | KVM_REG_MIPS_CP0_ERROREPC     | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH1    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH2    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH3    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH4    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH5    | 64
+  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH6    | 64
+  MIPS  | KVM_REG_MIPS_CP0_MAAR(0..63)  | 64
+  MIPS  | KVM_REG_MIPS_COUNT_CTL        | 64
+  MIPS  | KVM_REG_MIPS_COUNT_RESUME     | 64
+  MIPS  | KVM_REG_MIPS_COUNT_HZ         | 64
+  MIPS  | KVM_REG_MIPS_FPR_32(0..31)    | 32
+  MIPS  | KVM_REG_MIPS_FPR_64(0..31)    | 64
+  MIPS  | KVM_REG_MIPS_VEC_128(0..31)   | 128
+  MIPS  | KVM_REG_MIPS_FCR_IR           | 32
+  MIPS  | KVM_REG_MIPS_FCR_CSR          | 32
+  MIPS  | KVM_REG_MIPS_MSA_IR           | 32
+  MIPS  | KVM_REG_MIPS_MSA_CSR          | 32
+
+ARM registers are mapped using the lower 32 bits.  The upper 16 of that
+is the register group type, or coprocessor number:
+
+ARM core registers have the following id bit patterns:
+  0x4020 0000 0010 <index into the kvm_regs struct:16>
+
+ARM 32-bit CP15 registers have the following id bit patterns:
+  0x4020 0000 000F <zero:1> <crn:4> <crm:4> <opc1:4> <opc2:3>
+
+ARM 64-bit CP15 registers have the following id bit patterns:
+  0x4030 0000 000F <zero:1> <zero:4> <crm:4> <opc1:4> <zero:3>
+
+ARM CCSIDR registers are demultiplexed by CSSELR value:
+  0x4020 0000 0011 00 <csselr:8>
+
+ARM 32-bit VFP control registers have the following id bit patterns:
+  0x4020 0000 0012 1 <regno:12>
+
+ARM 64-bit FP registers have the following id bit patterns:
+  0x4030 0000 0012 0 <regno:12>
+
+ARM firmware pseudo-registers have the following bit pattern:
+  0x4030 0000 0014 <regno:16>
+
+
+arm64 registers are mapped using the lower 32 bits. The upper 16 of
+that is the register group type, or coprocessor number:
+
+arm64 core/FP-SIMD registers have the following id bit patterns. Note
+that the size of the access is variable, as the kvm_regs structure
+contains elements ranging from 32 to 128 bits. The index is a 32bit
+value in the kvm_regs structure seen as a 32bit array.
+  0x60x0 0000 0010 <index into the kvm_regs struct:16>
+
+Specifically:
+    Encoding            Register  Bits  kvm_regs member
+----------------------------------------------------------------
+  0x6030 0000 0010 0000 X0          64  regs.regs[0]
+  0x6030 0000 0010 0002 X1          64  regs.regs[1]
+    ...
+  0x6030 0000 0010 003c X30         64  regs.regs[30]
+  0x6030 0000 0010 003e SP          64  regs.sp
+  0x6030 0000 0010 0040 PC          64  regs.pc
+  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
+  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
+  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
+  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
+  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
+  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
+  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
+  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
+  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]    (*)
+  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]    (*)
+    ...
+  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]   (*)
+  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
+  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
+
+(*) These encodings are not accepted for SVE-enabled vcpus.  See
+    KVM_ARM_VCPU_INIT.
+
+    The equivalent register content can be accessed via bits [127:0] of
+    the corresponding SVE Zn registers instead for vcpus that have SVE
+    enabled (see below).
+
+arm64 CCSIDR registers are demultiplexed by CSSELR value:
+  0x6020 0000 0011 00 <csselr:8>
+
+arm64 system registers have the following id bit patterns:
+  0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
+
+arm64 firmware pseudo-registers have the following bit pattern:
+  0x6030 0000 0014 <regno:16>
+
+arm64 SVE registers have the following bit patterns:
+  0x6080 0000 0015 00 <n:5> <slice:5>   Zn bits[2048*slice + 2047 : 2048*slice]
+  0x6050 0000 0015 04 <n:4> <slice:5>   Pn bits[256*slice + 255 : 256*slice]
+  0x6050 0000 0015 060 <slice:5>        FFR bits[256*slice + 255 : 256*slice]
+  0x6060 0000 0015 ffff                 KVM_REG_ARM64_SVE_VLS pseudo-register
+
+Access to register IDs where 2048 * slice >= 128 * max_vq will fail with
+ENOENT.  max_vq is the vcpu's maximum supported vector length in 128-bit
+quadwords: see (**) below.
+
+These registers are only accessible on vcpus for which SVE is enabled.
+See KVM_ARM_VCPU_INIT for details.
+
+In addition, except for KVM_REG_ARM64_SVE_VLS, these registers are not
+accessible until the vcpu's SVE configuration has been finalized
+using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).  See KVM_ARM_VCPU_INIT
+and KVM_ARM_VCPU_FINALIZE for more information about this procedure.
+
+KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector
+lengths supported by the vcpu to be discovered and configured by
+userspace.  When transferred to or from user memory via KVM_GET_ONE_REG
+or KVM_SET_ONE_REG, the value of this register is of type
+__u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths as
+follows:
+
+__u64 vector_lengths[KVM_ARM64_SVE_VLS_WORDS];
+
+if (vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX &&
+    ((vector_lengths[(vq - KVM_ARM64_SVE_VQ_MIN) / 64] >>
+               ((vq - KVM_ARM64_SVE_VQ_MIN) % 64)) & 1))
+       /* Vector length vq * 16 bytes supported */
+else
+       /* Vector length vq * 16 bytes not supported */
+
+(**) The maximum value vq for which the above condition is true is
+max_vq.  This is the maximum vector length available to the guest on
+this vcpu, and determines which register slices are visible through
+this ioctl interface.
+
+(See Documentation/arm64/sve.rst for an explanation of the "vq"
+nomenclature.)
+
+KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT.
+KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that
+the host supports.
+
+Userspace may subsequently modify it if desired until the vcpu's SVE
+configuration is finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).
+
+Apart from simply removing all vector lengths from the host set that
+exceed some value, support for arbitrarily chosen sets of vector lengths
+is hardware-dependent and may not be available.  Attempting to configure
+an invalid set of vector lengths via KVM_SET_ONE_REG will fail with
+EINVAL.
+
+After the vcpu's SVE configuration is finalized, further attempts to
+write this register will fail with EPERM.
+
+
+MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
+the register group type:
+
+MIPS core registers (see above) have the following id bit patterns:
+  0x7030 0000 0000 <reg:16>
+
+MIPS CP0 registers (see KVM_REG_MIPS_CP0_* above) have the following id bit
+patterns depending on whether they're 32-bit or 64-bit registers:
+  0x7020 0000 0001 00 <reg:5> <sel:3>   (32-bit)
+  0x7030 0000 0001 00 <reg:5> <sel:3>   (64-bit)
+
+Note: KVM_REG_MIPS_CP0_ENTRYLO0 and KVM_REG_MIPS_CP0_ENTRYLO1 are the MIPS64
+versions of the EntryLo registers regardless of the word size of the host
+hardware, host kernel, guest, and whether XPA is present in the guest, i.e.
+with the RI and XI bits (if they exist) in bits 63 and 62 respectively, and
+the PFNX field starting at bit 30.
+
+MIPS MAARs (see KVM_REG_MIPS_CP0_MAAR(*) above) have the following id bit
+patterns:
+  0x7030 0000 0001 01 <reg:8>
+
+MIPS KVM control registers (see above) have the following id bit patterns:
+  0x7030 0000 0002 <reg:16>
+
+MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following
+id bit patterns depending on the size of the register being accessed. They are
+always accessed according to the current guest FPU mode (Status.FR and
+Config5.FRE), i.e. as the guest would see them, and they become unpredictable
+if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector
+registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they
+overlap the FPU registers:
+  0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
+  0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers)
+  0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers)
+
+MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the
+following id bit patterns:
+  0x7020 0000 0003 01 <0:3> <reg:5>
+
+MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the
+following id bit patterns:
+  0x7020 0000 0003 02 <0:3> <reg:5>
+
+
+4.69 KVM_GET_ONE_REG
+
+Capability: KVM_CAP_ONE_REG
+Architectures: all
+Type: vcpu ioctl
+Parameters: struct kvm_one_reg (in and out)
+Returns: 0 on success, negative value on failure
+Errors include:
+  ENOENT:   no such register
+  EINVAL:   invalid register ID, or no such register
+  EPERM:    (arm64) register access not allowed before vcpu finalization
+(These error codes are indicative only: do not rely on a specific error
+code being returned in a specific situation.)
+
+This ioctl allows to receive the value of a single register implemented
+in a vcpu. The register to read is indicated by the "id" field of the
+kvm_one_reg struct passed in. On success, the register value can be found
+at the memory location pointed to by "addr".
+
+The list of registers accessible using this interface is identical to the
+list in 4.68.
+
+
+4.70 KVM_KVMCLOCK_CTRL
+
+Capability: KVM_CAP_KVMCLOCK_CTRL
+Architectures: Any that implement pvclocks (currently x86 only)
+Type: vcpu ioctl
+Parameters: None
+Returns: 0 on success, -1 on error
+
+This signals to the host kernel that the specified guest is being paused by
+userspace.  The host will set a flag in the pvclock structure that is checked
+from the soft lockup watchdog.  The flag is part of the pvclock structure that
+is shared between guest and host, specifically the second bit of the flags
+field of the pvclock_vcpu_time_info structure.  It will be set exclusively by
+the host and read/cleared exclusively by the guest.  The guest operation of
+checking and clearing the flag must an atomic operation so
+load-link/store-conditional, or equivalent must be used.  There are two cases
+where the guest will clear the flag: when the soft lockup watchdog timer resets
+itself or when a soft lockup is detected.  This ioctl can be called any time
+after pausing the vcpu, but before it is resumed.
+
+
+4.71 KVM_SIGNAL_MSI
+
+Capability: KVM_CAP_SIGNAL_MSI
+Architectures: x86 arm arm64
+Type: vm ioctl
+Parameters: struct kvm_msi (in)
+Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
+
+Directly inject a MSI message. Only valid with in-kernel irqchip that handles
+MSI messages.
+
+struct kvm_msi {
+       __u32 address_lo;
+       __u32 address_hi;
+       __u32 data;
+       __u32 flags;
+       __u32 devid;
+       __u8  pad[12];
+};
+
+flags: KVM_MSI_VALID_DEVID: devid contains a valid value.  The per-VM
+  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
+  the device ID.  If this capability is not available, userspace
+  should never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
+
+If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
+for the device that wrote the MSI message.  For PCI, this is usually a
+BFD identifier in the lower 16 bits.
+
+On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
+feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
+address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
+address_hi must be zero.
+
+
+4.71 KVM_CREATE_PIT2
+
+Capability: KVM_CAP_PIT2
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pit_config (in)
+Returns: 0 on success, -1 on error
+
+Creates an in-kernel device model for the i8254 PIT. This call is only valid
+after enabling in-kernel irqchip support via KVM_CREATE_IRQCHIP. The following
+parameters have to be passed:
+
+struct kvm_pit_config {
+       __u32 flags;
+       __u32 pad[15];
+};
+
+Valid flags are:
+
+#define KVM_PIT_SPEAKER_DUMMY     1 /* emulate speaker port stub */
+
+PIT timer interrupts may use a per-VM kernel thread for injection. If it
+exists, this thread will have a name of the following pattern:
+
+kvm-pit/<owner-process-pid>
+
+When running a guest with elevated priorities, the scheduling parameters of
+this thread may have to be adjusted accordingly.
+
+This IOCTL replaces the obsolete KVM_CREATE_PIT.
+
+
+4.72 KVM_GET_PIT2
+
+Capability: KVM_CAP_PIT_STATE2
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pit_state2 (out)
+Returns: 0 on success, -1 on error
+
+Retrieves the state of the in-kernel PIT model. Only valid after
+KVM_CREATE_PIT2. The state is returned in the following structure:
+
+struct kvm_pit_state2 {
+       struct kvm_pit_channel_state channels[3];
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+Valid flags are:
+
+/* disable PIT in HPET legacy mode */
+#define KVM_PIT_FLAGS_HPET_LEGACY  0x00000001
+
+This IOCTL replaces the obsolete KVM_GET_PIT.
+
+
+4.73 KVM_SET_PIT2
+
+Capability: KVM_CAP_PIT_STATE2
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pit_state2 (in)
+Returns: 0 on success, -1 on error
+
+Sets the state of the in-kernel PIT model. Only valid after KVM_CREATE_PIT2.
+See KVM_GET_PIT2 for details on struct kvm_pit_state2.
+
+This IOCTL replaces the obsolete KVM_SET_PIT.
+
+
+4.74 KVM_PPC_GET_SMMU_INFO
+
+Capability: KVM_CAP_PPC_GET_SMMU_INFO
+Architectures: powerpc
+Type: vm ioctl
+Parameters: None
+Returns: 0 on success, -1 on error
+
+This populates and returns a structure describing the features of
+the "Server" class MMU emulation supported by KVM.
+This can in turn be used by userspace to generate the appropriate
+device-tree properties for the guest operating system.
+
+The structure contains some global information, followed by an
+array of supported segment page sizes:
+
+      struct kvm_ppc_smmu_info {
+            __u64 flags;
+            __u32 slb_size;
+            __u32 pad;
+            struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
+      };
+
+The supported flags are:
+
+    - KVM_PPC_PAGE_SIZES_REAL:
+        When that flag is set, guest page sizes must "fit" the backing
+        store page sizes. When not set, any page size in the list can
+        be used regardless of how they are backed by userspace.
+
+    - KVM_PPC_1T_SEGMENTS
+        The emulated MMU supports 1T segments in addition to the
+        standard 256M ones.
+
+    - KVM_PPC_NO_HASH
+       This flag indicates that HPT guests are not supported by KVM,
+       thus all guests must use radix MMU mode.
+
+The "slb_size" field indicates how many SLB entries are supported
+
+The "sps" array contains 8 entries indicating the supported base
+page sizes for a segment in increasing order. Each entry is defined
+as follow:
+
+   struct kvm_ppc_one_seg_page_size {
+       __u32 page_shift;       /* Base page shift of segment (or 0) */
+       __u32 slb_enc;          /* SLB encoding for BookS */
+       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
+   };
+
+An entry with a "page_shift" of 0 is unused. Because the array is
+organized in increasing order, a lookup can stop when encoutering
+such an entry.
+
+The "slb_enc" field provides the encoding to use in the SLB for the
+page size. The bits are in positions such as the value can directly
+be OR'ed into the "vsid" argument of the slbmte instruction.
+
+The "enc" array is a list which for each of those segment base page
+size provides the list of supported actual page sizes (which can be
+only larger or equal to the base page size), along with the
+corresponding encoding in the hash PTE. Similarly, the array is
+8 entries sorted by increasing sizes and an entry with a "0" shift
+is an empty entry and a terminator:
+
+   struct kvm_ppc_one_page_size {
+       __u32 page_shift;       /* Page shift (or 0) */
+       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
+   };
+
+The "pte_enc" field provides a value that can OR'ed into the hash
+PTE's RPN field (ie, it needs to be shifted left by 12 to OR it
+into the hash PTE second double word).
+
+4.75 KVM_IRQFD
+
+Capability: KVM_CAP_IRQFD
+Architectures: x86 s390 arm arm64
+Type: vm ioctl
+Parameters: struct kvm_irqfd (in)
+Returns: 0 on success, -1 on error
+
+Allows setting an eventfd to directly trigger a guest interrupt.
+kvm_irqfd.fd specifies the file descriptor to use as the eventfd and
+kvm_irqfd.gsi specifies the irqchip pin toggled by this event.  When
+an event is triggered on the eventfd, an interrupt is injected into
+the guest using the specified gsi pin.  The irqfd is removed using
+the KVM_IRQFD_FLAG_DEASSIGN flag, specifying both kvm_irqfd.fd
+and kvm_irqfd.gsi.
+
+With KVM_CAP_IRQFD_RESAMPLE, KVM_IRQFD supports a de-assert and notify
+mechanism allowing emulation of level-triggered, irqfd-based
+interrupts.  When KVM_IRQFD_FLAG_RESAMPLE is set the user must pass an
+additional eventfd in the kvm_irqfd.resamplefd field.  When operating
+in resample mode, posting of an interrupt through kvm_irq.fd asserts
+the specified gsi in the irqchip.  When the irqchip is resampled, such
+as from an EOI, the gsi is de-asserted and the user is notified via
+kvm_irqfd.resamplefd.  It is the user's responsibility to re-queue
+the interrupt if the device making use of it still requires service.
+Note that closing the resamplefd is not sufficient to disable the
+irqfd.  The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
+and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
+
+On arm/arm64, gsi routing being supported, the following can happen:
+- in case no routing entry is associated to this gsi, injection fails
+- in case the gsi is associated to an irqchip routing entry,
+  irqchip.pin + 32 corresponds to the injected SPI ID.
+- in case the gsi is associated to an MSI routing entry, the MSI
+  message and device ID are translated into an LPI (support restricted
+  to GICv3 ITS in-kernel emulation).
+
+4.76 KVM_PPC_ALLOCATE_HTAB
+
+Capability: KVM_CAP_PPC_ALLOC_HTAB
+Architectures: powerpc
+Type: vm ioctl
+Parameters: Pointer to u32 containing hash table order (in/out)
+Returns: 0 on success, -1 on error
+
+This requests the host kernel to allocate an MMU hash table for a
+guest using the PAPR paravirtualization interface.  This only does
+anything if the kernel is configured to use the Book 3S HV style of
+virtualization.  Otherwise the capability doesn't exist and the ioctl
+returns an ENOTTY error.  The rest of this description assumes Book 3S
+HV.
+
+There must be no vcpus running when this ioctl is called; if there
+are, it will do nothing and return an EBUSY error.
+
+The parameter is a pointer to a 32-bit unsigned integer variable
+containing the order (log base 2) of the desired size of the hash
+table, which must be between 18 and 46.  On successful return from the
+ioctl, the value will not be changed by the kernel.
+
+If no hash table has been allocated when any vcpu is asked to run
+(with the KVM_RUN ioctl), the host kernel will allocate a
+default-sized hash table (16 MB).
+
+If this ioctl is called when a hash table has already been allocated,
+with a different order from the existing hash table, the existing hash
+table will be freed and a new one allocated.  If this is ioctl is
+called when a hash table has already been allocated of the same order
+as specified, the kernel will clear out the existing hash table (zero
+all HPTEs).  In either case, if the guest is using the virtualized
+real-mode area (VRMA) facility, the kernel will re-create the VMRA
+HPTEs on the next KVM_RUN of any vcpu.
+
+4.77 KVM_S390_INTERRUPT
+
+Capability: basic
+Architectures: s390
+Type: vm ioctl, vcpu ioctl
+Parameters: struct kvm_s390_interrupt (in)
+Returns: 0 on success, -1 on error
+
+Allows to inject an interrupt to the guest. Interrupts can be floating
+(vm ioctl) or per cpu (vcpu ioctl), depending on the interrupt type.
+
+Interrupt parameters are passed via kvm_s390_interrupt:
+
+struct kvm_s390_interrupt {
+       __u32 type;
+       __u32 parm;
+       __u64 parm64;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP (vcpu) - sigp stop; optional flags in parm
+KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
+KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
+KVM_S390_RESTART (vcpu) - restart
+KVM_S390_INT_CLOCK_COMP (vcpu) - clock comparator interrupt
+KVM_S390_INT_CPU_TIMER (vcpu) - CPU timer interrupt
+KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
+                          parameters in parm and parm64
+KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
+KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
+KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
+KVM_S390_INT_IO(ai,cssid,ssid,schid) (vm) - compound value to indicate an
+    I/O interrupt (ai - adapter interrupt; cssid,ssid,schid - subchannel);
+    I/O interruption parameters in parm (subchannel) and parm64 (intparm,
+    interruption subclass)
+KVM_S390_MCHK (vm, vcpu) - machine check interrupt; cr 14 bits in parm,
+                           machine check interrupt code in parm64 (note that
+                           machine checks needing further payload are not
+                           supported by this ioctl)
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+4.78 KVM_PPC_GET_HTAB_FD
+
+Capability: KVM_CAP_PPC_HTAB_FD
+Architectures: powerpc
+Type: vm ioctl
+Parameters: Pointer to struct kvm_get_htab_fd (in)
+Returns: file descriptor number (>= 0) on success, -1 on error
+
+This returns a file descriptor that can be used either to read out the
+entries in the guest's hashed page table (HPT), or to write entries to
+initialize the HPT.  The returned fd can only be written to if the
+KVM_GET_HTAB_WRITE bit is set in the flags field of the argument, and
+can only be read if that bit is clear.  The argument struct looks like
+this:
+
+/* For KVM_PPC_GET_HTAB_FD */
+struct kvm_get_htab_fd {
+       __u64   flags;
+       __u64   start_index;
+       __u64   reserved[2];
+};
+
+/* Values for kvm_get_htab_fd.flags */
+#define KVM_GET_HTAB_BOLTED_ONLY       ((__u64)0x1)
+#define KVM_GET_HTAB_WRITE             ((__u64)0x2)
+
+The `start_index' field gives the index in the HPT of the entry at
+which to start reading.  It is ignored when writing.
+
+Reads on the fd will initially supply information about all
+"interesting" HPT entries.  Interesting entries are those with the
+bolted bit set, if the KVM_GET_HTAB_BOLTED_ONLY bit is set, otherwise
+all entries.  When the end of the HPT is reached, the read() will
+return.  If read() is called again on the fd, it will start again from
+the beginning of the HPT, but will only return HPT entries that have
+changed since they were last read.
+
+Data read or written is structured as a header (8 bytes) followed by a
+series of valid HPT entries (16 bytes) each.  The header indicates how
+many valid HPT entries there are and how many invalid entries follow
+the valid entries.  The invalid entries are not represented explicitly
+in the stream.  The header format is:
+
+struct kvm_get_htab_header {
+       __u32   index;
+       __u16   n_valid;
+       __u16   n_invalid;
+};
+
+Writes to the fd create HPT entries starting at the index given in the
+header; first `n_valid' valid entries with contents from the data
+written, then `n_invalid' invalid entries, invalidating any previously
+valid entries found.
+
+4.79 KVM_CREATE_DEVICE
+
+Capability: KVM_CAP_DEVICE_CTRL
+Type: vm ioctl
+Parameters: struct kvm_create_device (in/out)
+Returns: 0 on success, -1 on error
+Errors:
+  ENODEV: The device type is unknown or unsupported
+  EEXIST: Device already created, and this type of device may not
+          be instantiated multiple times
+
+  Other error conditions may be defined by individual device types or
+  have their standard meanings.
+
+Creates an emulated device in the kernel.  The file descriptor returned
+in fd can be used with KVM_SET/GET/HAS_DEVICE_ATTR.
+
+If the KVM_CREATE_DEVICE_TEST flag is set, only test whether the
+device type is supported (not necessarily whether it can be created
+in the current vm).
+
+Individual devices should not define flags.  Attributes should be used
+for specifying any behavior that is not implied by the device type
+number.
+
+struct kvm_create_device {
+       __u32   type;   /* in: KVM_DEV_TYPE_xxx */
+       __u32   fd;     /* out: device handle */
+       __u32   flags;  /* in: KVM_CREATE_DEVICE_xxx */
+};
+
+4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR
+
+Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
+  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
+Type: device ioctl, vm ioctl, vcpu ioctl
+Parameters: struct kvm_device_attr
+Returns: 0 on success, -1 on error
+Errors:
+  ENXIO:  The group or attribute is unknown/unsupported for this device
+          or hardware support is missing.
+  EPERM:  The attribute cannot (currently) be accessed this way
+          (e.g. read-only attribute, or attribute that only makes
+          sense when the device is in a different state)
+
+  Other error conditions may be defined by individual device types.
+
+Gets/sets a specified piece of device configuration and/or state.  The
+semantics are device-specific.  See individual device documentation in
+the "devices" directory.  As with ONE_REG, the size of the data
+transferred is defined by the particular attribute.
+
+struct kvm_device_attr {
+       __u32   flags;          /* no flags currently defined */
+       __u32   group;          /* device-defined */
+       __u64   attr;           /* group-defined */
+       __u64   addr;           /* userspace address of attr data */
+};
+
+4.81 KVM_HAS_DEVICE_ATTR
+
+Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
+  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
+Type: device ioctl, vm ioctl, vcpu ioctl
+Parameters: struct kvm_device_attr
+Returns: 0 on success, -1 on error
+Errors:
+  ENXIO:  The group or attribute is unknown/unsupported for this device
+          or hardware support is missing.
+
+Tests whether a device supports a particular attribute.  A successful
+return indicates the attribute is implemented.  It does not necessarily
+indicate that the attribute can be read or written in the device's
+current state.  "addr" is ignored.
+
+4.82 KVM_ARM_VCPU_INIT
+
+Capability: basic
+Architectures: arm, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_vcpu_init (in)
+Returns: 0 on success; -1 on error
+Errors:
+  EINVAL:    the target is unknown, or the combination of features is invalid.
+  ENOENT:    a features bit specified is unknown.
+
+This tells KVM what type of CPU to present to the guest, and what
+optional features it should have.  This will cause a reset of the cpu
+registers to their initial values.  If this is not called, KVM_RUN will
+return ENOEXEC for that vcpu.
+
+Note that because some registers reflect machine topology, all vcpus
+should be created before this ioctl is invoked.
+
+Userspace can call this function multiple times for a given vcpu, including
+after the vcpu has been run. This will reset the vcpu to its initial
+state. All calls to this function after the initial call must use the same
+target and same set of feature flags, otherwise EINVAL will be returned.
+
+Possible features:
+       - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
+         Depends on KVM_CAP_ARM_PSCI.  If not set, the CPU will be powered on
+         and execute guest code when KVM_RUN is called.
+       - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
+         Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
+       - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
+          backward compatible with v0.2) for the CPU.
+         Depends on KVM_CAP_ARM_PSCI_0_2.
+       - KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
+         Depends on KVM_CAP_ARM_PMU_V3.
+
+       - KVM_ARM_VCPU_PTRAUTH_ADDRESS: Enables Address Pointer authentication
+         for arm64 only.
+         Depends on KVM_CAP_ARM_PTRAUTH_ADDRESS.
+         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
+         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
+         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
+         requested.
+
+       - KVM_ARM_VCPU_PTRAUTH_GENERIC: Enables Generic Pointer authentication
+         for arm64 only.
+         Depends on KVM_CAP_ARM_PTRAUTH_GENERIC.
+         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
+         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
+         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
+         requested.
+
+       - KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only).
+         Depends on KVM_CAP_ARM_SVE.
+         Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+
+          * After KVM_ARM_VCPU_INIT:
+
+             - KVM_REG_ARM64_SVE_VLS may be read using KVM_GET_ONE_REG: the
+               initial value of this pseudo-register indicates the best set of
+               vector lengths possible for a vcpu on this host.
+
+          * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+
+             - KVM_RUN and KVM_GET_REG_LIST are not available;
+
+             - KVM_GET_ONE_REG and KVM_SET_ONE_REG cannot be used to access
+               the scalable archietctural SVE registers
+               KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() or
+               KVM_REG_ARM64_SVE_FFR;
+
+             - KVM_REG_ARM64_SVE_VLS may optionally be written using
+               KVM_SET_ONE_REG, to modify the set of vector lengths available
+               for the vcpu.
+
+          * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
+
+             - the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can
+               no longer be written using KVM_SET_ONE_REG.
+
+4.83 KVM_ARM_PREFERRED_TARGET
+
+Capability: basic
+Architectures: arm, arm64
+Type: vm ioctl
+Parameters: struct struct kvm_vcpu_init (out)
+Returns: 0 on success; -1 on error
+Errors:
+  ENODEV:    no preferred target available for the host
+
+This queries KVM for preferred CPU target type which can be emulated
+by KVM on underlying host.
+
+The ioctl returns struct kvm_vcpu_init instance containing information
+about preferred CPU target type and recommended features for it.  The
+kvm_vcpu_init->features bitmap returned will have feature bits set if
+the preferred target recommends setting these features, but this is
+not mandatory.
+
+The information returned by this ioctl can be used to prepare an instance
+of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in
+in VCPU matching underlying host.
+
+
+4.84 KVM_GET_REG_LIST
+
+Capability: basic
+Architectures: arm, arm64, mips
+Type: vcpu ioctl
+Parameters: struct kvm_reg_list (in/out)
+Returns: 0 on success; -1 on error
+Errors:
+  E2BIG:     the reg index list is too big to fit in the array specified by
+             the user (the number required will be written into n).
+
+struct kvm_reg_list {
+       __u64 n; /* number of registers in reg[] */
+       __u64 reg[0];
+};
+
+This ioctl returns the guest registers that are supported for the
+KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
+
+
+4.85 KVM_ARM_SET_DEVICE_ADDR (deprecated)
+
+Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
+Architectures: arm, arm64
+Type: vm ioctl
+Parameters: struct kvm_arm_device_address (in)
+Returns: 0 on success, -1 on error
+Errors:
+  ENODEV: The device id is unknown
+  ENXIO:  Device not supported on current system
+  EEXIST: Address already set
+  E2BIG:  Address outside guest physical address space
+  EBUSY:  Address overlaps with other device range
+
+struct kvm_arm_device_addr {
+       __u64 id;
+       __u64 addr;
+};
+
+Specify a device address in the guest's physical address space where guests
+can access emulated or directly exposed devices, which the host kernel needs
+to know about. The id field is an architecture specific identifier for a
+specific device.
+
+ARM/arm64 divides the id field into two parts, a device id and an
+address type id specific to the individual device.
+
+  bits:  | 63        ...       32 | 31    ...    16 | 15    ...    0 |
+  field: |        0x00000000      |     device id   |  addr type id  |
+
+ARM/arm64 currently only require this when using the in-kernel GIC
+support for the hardware VGIC features, using KVM_ARM_DEVICE_VGIC_V2
+as the device id.  When setting the base address for the guest's
+mapping of the VGIC virtual CPU and distributor interface, the ioctl
+must be called after calling KVM_CREATE_IRQCHIP, but before calling
+KVM_RUN on any of the VCPUs.  Calling this ioctl twice for any of the
+base addresses will return -EEXIST.
+
+Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
+should be used instead.
+
+
+4.86 KVM_PPC_RTAS_DEFINE_TOKEN
+
+Capability: KVM_CAP_PPC_RTAS
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_rtas_token_args
+Returns: 0 on success, -1 on error
+
+Defines a token value for a RTAS (Run Time Abstraction Services)
+service in order to allow it to be handled in the kernel.  The
+argument struct gives the name of the service, which must be the name
+of a service that has a kernel-side implementation.  If the token
+value is non-zero, it will be associated with that service, and
+subsequent RTAS calls by the guest specifying that token will be
+handled by the kernel.  If the token value is 0, then any token
+associated with the service will be forgotten, and subsequent RTAS
+calls by the guest for that service will be passed to userspace to be
+handled.
+
+4.87 KVM_SET_GUEST_DEBUG
+
+Capability: KVM_CAP_SET_GUEST_DEBUG
+Architectures: x86, s390, ppc, arm64
+Type: vcpu ioctl
+Parameters: struct kvm_guest_debug (in)
+Returns: 0 on success; -1 on error
+
+struct kvm_guest_debug {
+       __u32 control;
+       __u32 pad;
+       struct kvm_guest_debug_arch arch;
+};
+
+Set up the processor specific debug registers and configure vcpu for
+handling guest debug events. There are two parts to the structure, the
+first a control bitfield indicates the type of debug events to handle
+when running. Common control bits are:
+
+  - KVM_GUESTDBG_ENABLE:        guest debugging is enabled
+  - KVM_GUESTDBG_SINGLESTEP:    the next run should single-step
+
+The top 16 bits of the control field are architecture specific control
+flags which can include the following:
+
+  - KVM_GUESTDBG_USE_SW_BP:     using software breakpoints [x86, arm64]
+  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390, arm64]
+  - KVM_GUESTDBG_INJECT_DB:     inject DB type exception [x86]
+  - KVM_GUESTDBG_INJECT_BP:     inject BP type exception [x86]
+  - KVM_GUESTDBG_EXIT_PENDING:  trigger an immediate guest exit [s390]
+
+For example KVM_GUESTDBG_USE_SW_BP indicates that software breakpoints
+are enabled in memory so we need to ensure breakpoint exceptions are
+correctly trapped and the KVM run loop exits at the breakpoint and not
+running off into the normal guest vector. For KVM_GUESTDBG_USE_HW_BP
+we need to ensure the guest vCPUs architecture specific registers are
+updated to the correct (supplied) values.
+
+The second part of the structure is architecture specific and
+typically contains a set of debug registers.
+
+For arm64 the number of debug registers is implementation defined and
+can be determined by querying the KVM_CAP_GUEST_DEBUG_HW_BPS and
+KVM_CAP_GUEST_DEBUG_HW_WPS capabilities which return a positive number
+indicating the number of supported registers.
+
+When debug events exit the main run loop with the reason
+KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
+structure containing architecture specific debug information.
+
+4.88 KVM_GET_EMULATED_CPUID
+
+Capability: KVM_CAP_EXT_EMUL_CPUID
+Architectures: x86
+Type: system ioctl
+Parameters: struct kvm_cpuid2 (in/out)
+Returns: 0 on success, -1 on error
+
+struct kvm_cpuid2 {
+       __u32 nent;
+       __u32 flags;
+       struct kvm_cpuid_entry2 entries[0];
+};
+
+The member 'flags' is used for passing flags from userspace.
+
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
+
+struct kvm_cpuid_entry2 {
+       __u32 function;
+       __u32 index;
+       __u32 flags;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding[3];
+};
+
+This ioctl returns x86 cpuid features which are emulated by
+kvm.Userspace can use the information returned by this ioctl to query
+which features are emulated by kvm instead of being present natively.
+
+Userspace invokes KVM_GET_EMULATED_CPUID by passing a kvm_cpuid2
+structure with the 'nent' field indicating the number of entries in
+the variable-size array 'entries'. If the number of entries is too low
+to describe the cpu capabilities, an error (E2BIG) is returned. If the
+number is too high, the 'nent' field is adjusted and an error (ENOMEM)
+is returned. If the number is just right, the 'nent' field is adjusted
+to the number of valid entries in the 'entries' array, which is then
+filled.
+
+The entries returned are the set CPUID bits of the respective features
+which kvm emulates, as returned by the CPUID instruction, with unknown
+or unsupported feature bits cleared.
+
+Features like x2apic, for example, may not be present in the host cpu
+but are exposed by kvm in KVM_GET_SUPPORTED_CPUID because they can be
+emulated efficiently and thus not included here.
+
+The fields in each entry are defined as follows:
+
+  function: the eax value used to obtain the entry
+  index: the ecx value used to obtain the entry (for entries that are
+         affected by ecx)
+  flags: an OR of zero or more of the following:
+        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
+           if the index field is valid
+        KVM_CPUID_FLAG_STATEFUL_FUNC:
+           if cpuid for this function returns different values for successive
+           invocations; there will be several entries with the same function,
+           all with this flag set
+        KVM_CPUID_FLAG_STATE_READ_NEXT:
+           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
+           the first entry to be read by a cpu
+   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
+         this function/index combination
+
+4.89 KVM_S390_MEM_OP
+
+Capability: KVM_CAP_S390_MEM_OP
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_mem_op (in)
+Returns: = 0 on success,
+         < 0 on generic error (e.g. -EFAULT or -ENOMEM),
+         > 0 if an exception occurred while walking the page tables
+
+Read or write data from/to the logical (virtual) memory of a VCPU.
+
+Parameters are specified via the following structure:
+
+struct kvm_s390_mem_op {
+       __u64 gaddr;            /* the guest address */
+       __u64 flags;            /* flags */
+       __u32 size;             /* amount of bytes */
+       __u32 op;               /* type of operation */
+       __u64 buf;              /* buffer in userspace */
+       __u8 ar;                /* the access register number */
+       __u8 reserved[31];      /* should be set to 0 */
+};
+
+The type of operation is specified in the "op" field. It is either
+KVM_S390_MEMOP_LOGICAL_READ for reading from logical memory space or
+KVM_S390_MEMOP_LOGICAL_WRITE for writing to logical memory space. The
+KVM_S390_MEMOP_F_CHECK_ONLY flag can be set in the "flags" field to check
+whether the corresponding memory access would create an access exception
+(without touching the data in the memory at the destination). In case an
+access exception occurred while walking the MMU tables of the guest, the
+ioctl returns a positive error number to indicate the type of exception.
+This exception is also raised directly at the corresponding VCPU if the
+flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field.
+
+The start address of the memory region has to be specified in the "gaddr"
+field, and the length of the region in the "size" field. "buf" is the buffer
+supplied by the userspace application where the read data should be written
+to for KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written
+is stored for a KVM_S390_MEMOP_LOGICAL_WRITE. "buf" is unused and can be NULL
+when KVM_S390_MEMOP_F_CHECK_ONLY is specified. "ar" designates the access
+register number to be used.
+
+The "reserved" field is meant for future extensions. It is not used by
+KVM with the currently defined set of flags.
+
+4.90 KVM_S390_GET_SKEYS
+
+Capability: KVM_CAP_S390_SKEYS
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_skeys
+Returns: 0 on success, KVM_S390_GET_KEYS_NONE if guest is not using storage
+         keys, negative value on error
+
+This ioctl is used to get guest storage key values on the s390
+architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
+
+struct kvm_s390_skeys {
+       __u64 start_gfn;
+       __u64 count;
+       __u64 skeydata_addr;
+       __u32 flags;
+       __u32 reserved[9];
+};
+
+The start_gfn field is the number of the first guest frame whose storage keys
+you want to get.
+
+The count field is the number of consecutive frames (starting from start_gfn)
+whose storage keys to get. The count field must be at least 1 and the maximum
+allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
+will cause the ioctl to return -EINVAL.
+
+The skeydata_addr field is the address to a buffer large enough to hold count
+bytes. This buffer will be filled with storage key data by the ioctl.
+
+4.91 KVM_S390_SET_SKEYS
+
+Capability: KVM_CAP_S390_SKEYS
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_skeys
+Returns: 0 on success, negative value on error
+
+This ioctl is used to set guest storage key values on the s390
+architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
+See section on KVM_S390_GET_SKEYS for struct definition.
+
+The start_gfn field is the number of the first guest frame whose storage keys
+you want to set.
+
+The count field is the number of consecutive frames (starting from start_gfn)
+whose storage keys to get. The count field must be at least 1 and the maximum
+allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
+will cause the ioctl to return -EINVAL.
+
+The skeydata_addr field is the address to a buffer containing count bytes of
+storage keys. Each byte in the buffer will be set as the storage key for a
+single frame starting at start_gfn for count frames.
+
+Note: If any architecturally invalid key value is found in the given data then
+the ioctl will return -EINVAL.
+
+4.92 KVM_S390_IRQ
+
+Capability: KVM_CAP_S390_INJECT_IRQ
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq (in)
+Returns: 0 on success, -1 on error
+Errors:
+  EINVAL: interrupt type is invalid
+          type is KVM_S390_SIGP_STOP and flag parameter is invalid value
+          type is KVM_S390_INT_EXTERNAL_CALL and code is bigger
+            than the maximum of VCPUs
+  EBUSY:  type is KVM_S390_SIGP_SET_PREFIX and vcpu is not stopped
+          type is KVM_S390_SIGP_STOP and a stop irq is already pending
+          type is KVM_S390_INT_EXTERNAL_CALL and an external call interrupt
+            is already pending
+
+Allows to inject an interrupt to the guest.
+
+Using struct kvm_s390_irq as a parameter allows
+to inject additional payload which is not
+possible via KVM_S390_INTERRUPT.
+
+Interrupt parameters are passed via kvm_s390_irq:
+
+struct kvm_s390_irq {
+       __u64 type;
+       union {
+               struct kvm_s390_io_info io;
+               struct kvm_s390_ext_info ext;
+               struct kvm_s390_pgm_info pgm;
+               struct kvm_s390_emerg_info emerg;
+               struct kvm_s390_extcall_info extcall;
+               struct kvm_s390_prefix_info prefix;
+               struct kvm_s390_stop_info stop;
+               struct kvm_s390_mchk_info mchk;
+               char reserved[64];
+       } u;
+};
+
+type can be one of the following:
+
+KVM_S390_SIGP_STOP - sigp stop; parameter in .stop
+KVM_S390_PROGRAM_INT - program check; parameters in .pgm
+KVM_S390_SIGP_SET_PREFIX - sigp set prefix; parameters in .prefix
+KVM_S390_RESTART - restart; no parameters
+KVM_S390_INT_CLOCK_COMP - clock comparator interrupt; no parameters
+KVM_S390_INT_CPU_TIMER - CPU timer interrupt; no parameters
+KVM_S390_INT_EMERGENCY - sigp emergency; parameters in .emerg
+KVM_S390_INT_EXTERNAL_CALL - sigp external call; parameters in .extcall
+KVM_S390_MCHK - machine check interrupt; parameters in .mchk
+
+This is an asynchronous vcpu ioctl and can be invoked from any thread.
+
+4.94 KVM_S390_GET_IRQ_STATE
+
+Capability: KVM_CAP_S390_IRQ_STATE
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq_state (out)
+Returns: >= number of bytes copied into buffer,
+         -EINVAL if buffer size is 0,
+         -ENOBUFS if buffer size is too small to fit all pending interrupts,
+         -EFAULT if the buffer address was invalid
+
+This ioctl allows userspace to retrieve the complete state of all currently
+pending interrupts in a single buffer. Use cases include migration
+and introspection. The parameter structure contains the address of a
+userspace buffer and its length:
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;        /* will stay unused for compatibility reasons */
+       __u32 len;
+       __u32 reserved[4];  /* will stay unused for compatibility reasons */
+};
+
+Userspace passes in the above struct and for each pending interrupt a
+struct kvm_s390_irq is copied to the provided buffer.
+
+The structure contains a flags and a reserved field for future extensions. As
+the kernel never checked for flags == 0 and QEMU never pre-zeroed flags and
+reserved, these fields can not be used in the future without breaking
+compatibility.
+
+If -ENOBUFS is returned the buffer provided was too small and userspace
+may retry with a bigger buffer.
+
+4.95 KVM_S390_SET_IRQ_STATE
+
+Capability: KVM_CAP_S390_IRQ_STATE
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_irq_state (in)
+Returns: 0 on success,
+         -EFAULT if the buffer address was invalid,
+         -EINVAL for an invalid buffer length (see below),
+         -EBUSY if there were already interrupts pending,
+         errors occurring when actually injecting the
+          interrupt. See KVM_S390_IRQ.
+
+This ioctl allows userspace to set the complete state of all cpu-local
+interrupts currently pending for the vcpu. It is intended for restoring
+interrupt state after a migration. The input parameter is a userspace buffer
+containing a struct kvm_s390_irq_state:
+
+struct kvm_s390_irq_state {
+       __u64 buf;
+       __u32 flags;        /* will stay unused for compatibility reasons */
+       __u32 len;
+       __u32 reserved[4];  /* will stay unused for compatibility reasons */
+};
+
+The restrictions for flags and reserved apply as well.
+(see KVM_S390_GET_IRQ_STATE)
+
+The userspace memory referenced by buf contains a struct kvm_s390_irq
+for each interrupt to be injected into the guest.
+If one of the interrupts could not be injected for some reason the
+ioctl aborts.
+
+len must be a multiple of sizeof(struct kvm_s390_irq). It must be > 0
+and it must not exceed (max_vcpus + 32) * sizeof(struct kvm_s390_irq),
+which is the maximum number of possibly pending cpu-local interrupts.
+
+4.96 KVM_SMI
+
+Capability: KVM_CAP_X86_SMM
+Architectures: x86
+Type: vcpu ioctl
+Parameters: none
+Returns: 0 on success, -1 on error
+
+Queues an SMI on the thread's vcpu.
+
+4.97 KVM_CAP_PPC_MULTITCE
+
+Capability: KVM_CAP_PPC_MULTITCE
+Architectures: ppc
+Type: vm
+
+This capability means the kernel is capable of handling hypercalls
+H_PUT_TCE_INDIRECT and H_STUFF_TCE without passing those into the user
+space. This significantly accelerates DMA operations for PPC KVM guests.
+User space should expect that its handlers for these hypercalls
+are not going to be called if user space previously registered LIOBN
+in KVM (via KVM_CREATE_SPAPR_TCE or similar calls).
+
+In order to enable H_PUT_TCE_INDIRECT and H_STUFF_TCE use in the guest,
+user space might have to advertise it for the guest. For example,
+IBM pSeries (sPAPR) guest starts using them if "hcall-multi-tce" is
+present in the "ibm,hypertas-functions" device-tree property.
+
+The hypercalls mentioned above may or may not be processed successfully
+in the kernel based fast path. If they can not be handled by the kernel,
+they will get passed on to user space. So user space still has to have
+an implementation for these despite the in kernel acceleration.
+
+This capability is always enabled.
+
+4.98 KVM_CREATE_SPAPR_TCE_64
+
+Capability: KVM_CAP_SPAPR_TCE_64
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_create_spapr_tce_64 (in)
+Returns: file descriptor for manipulating the created TCE table
+
+This is an extension for KVM_CAP_SPAPR_TCE which only supports 32bit
+windows, described in 4.62 KVM_CREATE_SPAPR_TCE
+
+This capability uses extended struct in ioctl interface:
+
+/* for KVM_CAP_SPAPR_TCE_64 */
+struct kvm_create_spapr_tce_64 {
+       __u64 liobn;
+       __u32 page_shift;
+       __u32 flags;
+       __u64 offset;   /* in pages */
+       __u64 size;     /* in pages */
+};
+
+The aim of extension is to support an additional bigger DMA window with
+a variable page size.
+KVM_CREATE_SPAPR_TCE_64 receives a 64bit window size, an IOMMU page shift and
+a bus offset of the corresponding DMA window, @size and @offset are numbers
+of IOMMU pages.
+
+@flags are not used at the moment.
+
+The rest of functionality is identical to KVM_CREATE_SPAPR_TCE.
+
+4.99 KVM_REINJECT_CONTROL
+
+Capability: KVM_CAP_REINJECT_CONTROL
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_reinject_control (in)
+Returns: 0 on success,
+         -EFAULT if struct kvm_reinject_control cannot be read,
+         -ENXIO if KVM_CREATE_PIT or KVM_CREATE_PIT2 didn't succeed earlier.
+
+i8254 (PIT) has two modes, reinject and !reinject.  The default is reinject,
+where KVM queues elapsed i8254 ticks and monitors completion of interrupt from
+vector(s) that i8254 injects.  Reinject mode dequeues a tick and injects its
+interrupt whenever there isn't a pending interrupt from i8254.
+!reinject mode injects an interrupt as soon as a tick arrives.
+
+struct kvm_reinject_control {
+       __u8 pit_reinject;
+       __u8 reserved[31];
+};
+
+pit_reinject = 0 (!reinject mode) is recommended, unless running an old
+operating system that uses the PIT for timing (e.g. Linux 2.4.x).
+
+4.100 KVM_PPC_CONFIGURE_V3_MMU
+
+Capability: KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_ppc_mmuv3_cfg (in)
+Returns: 0 on success,
+         -EFAULT if struct kvm_ppc_mmuv3_cfg cannot be read,
+         -EINVAL if the configuration is invalid
+
+This ioctl controls whether the guest will use radix or HPT (hashed
+page table) translation, and sets the pointer to the process table for
+the guest.
+
+struct kvm_ppc_mmuv3_cfg {
+       __u64   flags;
+       __u64   process_table;
+};
+
+There are two bits that can be set in flags; KVM_PPC_MMUV3_RADIX and
+KVM_PPC_MMUV3_GTSE.  KVM_PPC_MMUV3_RADIX, if set, configures the guest
+to use radix tree translation, and if clear, to use HPT translation.
+KVM_PPC_MMUV3_GTSE, if set and if KVM permits it, configures the guest
+to be able to use the global TLB and SLB invalidation instructions;
+if clear, the guest may not use these instructions.
+
+The process_table field specifies the address and size of the guest
+process table, which is in the guest's space.  This field is formatted
+as the second doubleword of the partition table entry, as defined in
+the Power ISA V3.00, Book III section 5.7.6.1.
+
+4.101 KVM_PPC_GET_RMMU_INFO
+
+Capability: KVM_CAP_PPC_RADIX_MMU
+Architectures: ppc
+Type: vm ioctl
+Parameters: struct kvm_ppc_rmmu_info (out)
+Returns: 0 on success,
+        -EFAULT if struct kvm_ppc_rmmu_info cannot be written,
+        -EINVAL if no useful information can be returned
+
+This ioctl returns a structure containing two things: (a) a list
+containing supported radix tree geometries, and (b) a list that maps
+page sizes to put in the "AP" (actual page size) field for the tlbie
+(TLB invalidate entry) instruction.
+
+struct kvm_ppc_rmmu_info {
+       struct kvm_ppc_radix_geom {
+               __u8    page_shift;
+               __u8    level_bits[4];
+               __u8    pad[3];
+       }       geometries[8];
+       __u32   ap_encodings[8];
+};
+
+The geometries[] field gives up to 8 supported geometries for the
+radix page table, in terms of the log base 2 of the smallest page
+size, and the number of bits indexed at each level of the tree, from
+the PTE level up to the PGD level in that order.  Any unused entries
+will have 0 in the page_shift field.
+
+The ap_encodings gives the supported page sizes and their AP field
+encodings, encoded with the AP value in the top 3 bits and the log
+base 2 of the page size in the bottom 6 bits.
+
+4.102 KVM_PPC_RESIZE_HPT_PREPARE
+
+Capability: KVM_CAP_SPAPR_RESIZE_HPT
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_ppc_resize_hpt (in)
+Returns: 0 on successful completion,
+        >0 if a new HPT is being prepared, the value is an estimated
+             number of milliseconds until preparation is complete
+         -EFAULT if struct kvm_reinject_control cannot be read,
+        -EINVAL if the supplied shift or flags are invalid
+        -ENOMEM if unable to allocate the new HPT
+        -ENOSPC if there was a hash collision when moving existing
+                  HPT entries to the new HPT
+        -EIO on other error conditions
+
+Used to implement the PAPR extension for runtime resizing of a guest's
+Hashed Page Table (HPT).  Specifically this starts, stops or monitors
+the preparation of a new potential HPT for the guest, essentially
+implementing the H_RESIZE_HPT_PREPARE hypercall.
+
+If called with shift > 0 when there is no pending HPT for the guest,
+this begins preparation of a new pending HPT of size 2^(shift) bytes.
+It then returns a positive integer with the estimated number of
+milliseconds until preparation is complete.
+
+If called when there is a pending HPT whose size does not match that
+requested in the parameters, discards the existing pending HPT and
+creates a new one as above.
+
+If called when there is a pending HPT of the size requested, will:
+  * If preparation of the pending HPT is already complete, return 0
+  * If preparation of the pending HPT has failed, return an error
+    code, then discard the pending HPT.
+  * If preparation of the pending HPT is still in progress, return an
+    estimated number of milliseconds until preparation is complete.
+
+If called with shift == 0, discards any currently pending HPT and
+returns 0 (i.e. cancels any in-progress preparation).
+
+flags is reserved for future expansion, currently setting any bits in
+flags will result in an -EINVAL.
+
+Normally this will be called repeatedly with the same parameters until
+it returns <= 0.  The first call will initiate preparation, subsequent
+ones will monitor preparation until it completes or fails.
+
+struct kvm_ppc_resize_hpt {
+       __u64 flags;
+       __u32 shift;
+       __u32 pad;
+};
+
+4.103 KVM_PPC_RESIZE_HPT_COMMIT
+
+Capability: KVM_CAP_SPAPR_RESIZE_HPT
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_ppc_resize_hpt (in)
+Returns: 0 on successful completion,
+         -EFAULT if struct kvm_reinject_control cannot be read,
+        -EINVAL if the supplied shift or flags are invalid
+        -ENXIO is there is no pending HPT, or the pending HPT doesn't
+                 have the requested size
+        -EBUSY if the pending HPT is not fully prepared
+        -ENOSPC if there was a hash collision when moving existing
+                  HPT entries to the new HPT
+        -EIO on other error conditions
+
+Used to implement the PAPR extension for runtime resizing of a guest's
+Hashed Page Table (HPT).  Specifically this requests that the guest be
+transferred to working with the new HPT, essentially implementing the
+H_RESIZE_HPT_COMMIT hypercall.
+
+This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has
+returned 0 with the same parameters.  In other cases
+KVM_PPC_RESIZE_HPT_COMMIT will return an error (usually -ENXIO or
+-EBUSY, though others may be possible if the preparation was started,
+but failed).
+
+This will have undefined effects on the guest if it has not already
+placed itself in a quiescent state where no vcpu will make MMU enabled
+memory accesses.
+
+On succsful completion, the pending HPT will become the guest's active
+HPT and the previous HPT will be discarded.
+
+On failure, the guest will still be operating on its previous HPT.
+
+struct kvm_ppc_resize_hpt {
+       __u64 flags;
+       __u32 shift;
+       __u32 pad;
+};
+
+4.104 KVM_X86_GET_MCE_CAP_SUPPORTED
+
+Capability: KVM_CAP_MCE
+Architectures: x86
+Type: system ioctl
+Parameters: u64 mce_cap (out)
+Returns: 0 on success, -1 on error
+
+Returns supported MCE capabilities. The u64 mce_cap parameter
+has the same format as the MSR_IA32_MCG_CAP register. Supported
+capabilities will have the corresponding bits set.
+
+4.105 KVM_X86_SETUP_MCE
+
+Capability: KVM_CAP_MCE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: u64 mcg_cap (in)
+Returns: 0 on success,
+         -EFAULT if u64 mcg_cap cannot be read,
+         -EINVAL if the requested number of banks is invalid,
+         -EINVAL if requested MCE capability is not supported.
+
+Initializes MCE support for use. The u64 mcg_cap parameter
+has the same format as the MSR_IA32_MCG_CAP register and
+specifies which capabilities should be enabled. The maximum
+supported number of error-reporting banks can be retrieved when
+checking for KVM_CAP_MCE. The supported capabilities can be
+retrieved with KVM_X86_GET_MCE_CAP_SUPPORTED.
+
+4.106 KVM_X86_SET_MCE
+
+Capability: KVM_CAP_MCE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_x86_mce (in)
+Returns: 0 on success,
+         -EFAULT if struct kvm_x86_mce cannot be read,
+         -EINVAL if the bank number is invalid,
+         -EINVAL if VAL bit is not set in status field.
+
+Inject a machine check error (MCE) into the guest. The input
+parameter is:
+
+struct kvm_x86_mce {
+       __u64 status;
+       __u64 addr;
+       __u64 misc;
+       __u64 mcg_status;
+       __u8 bank;
+       __u8 pad1[7];
+       __u64 pad2[3];
+};
+
+If the MCE being reported is an uncorrected error, KVM will
+inject it as an MCE exception into the guest. If the guest
+MCG_STATUS register reports that an MCE is in progress, KVM
+causes an KVM_EXIT_SHUTDOWN vmexit.
+
+Otherwise, if the MCE is a corrected error, KVM will just
+store it in the corresponding bank (provided this bank is
+not holding a previously reported uncorrected error).
+
+4.107 KVM_S390_GET_CMMA_BITS
+
+Capability: KVM_CAP_S390_CMMA_MIGRATION
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_cmma_log (in, out)
+Returns: 0 on success, a negative value on error
+
+This ioctl is used to get the values of the CMMA bits on the s390
+architecture. It is meant to be used in two scenarios:
+- During live migration to save the CMMA values. Live migration needs
+  to be enabled via the KVM_REQ_START_MIGRATION VM property.
+- To non-destructively peek at the CMMA values, with the flag
+  KVM_S390_CMMA_PEEK set.
+
+The ioctl takes parameters via the kvm_s390_cmma_log struct. The desired
+values are written to a buffer whose location is indicated via the "values"
+member in the kvm_s390_cmma_log struct.  The values in the input struct are
+also updated as needed.
+Each CMMA value takes up one byte.
+
+struct kvm_s390_cmma_log {
+       __u64 start_gfn;
+       __u32 count;
+       __u32 flags;
+       union {
+               __u64 remaining;
+               __u64 mask;
+       };
+       __u64 values;
+};
+
+start_gfn is the number of the first guest frame whose CMMA values are
+to be retrieved,
+
+count is the length of the buffer in bytes,
+
+values points to the buffer where the result will be written to.
+
+If count is greater than KVM_S390_SKEYS_MAX, then it is considered to be
+KVM_S390_SKEYS_MAX. KVM_S390_SKEYS_MAX is re-used for consistency with
+other ioctls.
+
+The result is written in the buffer pointed to by the field values, and
+the values of the input parameter are updated as follows.
+
+Depending on the flags, different actions are performed. The only
+supported flag so far is KVM_S390_CMMA_PEEK.
+
+The default behaviour if KVM_S390_CMMA_PEEK is not set is:
+start_gfn will indicate the first page frame whose CMMA bits were dirty.
+It is not necessarily the same as the one passed as input, as clean pages
+are skipped.
+
+count will indicate the number of bytes actually written in the buffer.
+It can (and very often will) be smaller than the input value, since the
+buffer is only filled until 16 bytes of clean values are found (which
+are then not copied in the buffer). Since a CMMA migration block needs
+the base address and the length, for a total of 16 bytes, we will send
+back some clean data if there is some dirty data afterwards, as long as
+the size of the clean data does not exceed the size of the header. This
+allows to minimize the amount of data to be saved or transferred over
+the network at the expense of more roundtrips to userspace. The next
+invocation of the ioctl will skip over all the clean values, saving
+potentially more than just the 16 bytes we found.
+
+If KVM_S390_CMMA_PEEK is set:
+the existing storage attributes are read even when not in migration
+mode, and no other action is performed;
+
+the output start_gfn will be equal to the input start_gfn,
+
+the output count will be equal to the input count, except if the end of
+memory has been reached.
+
+In both cases:
+the field "remaining" will indicate the total number of dirty CMMA values
+still remaining, or 0 if KVM_S390_CMMA_PEEK is set and migration mode is
+not enabled.
+
+mask is unused.
+
+values points to the userspace buffer where the result will be stored.
+
+This ioctl can fail with -ENOMEM if not enough memory can be allocated to
+complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
+KVM_S390_CMMA_PEEK is not set but migration mode was not enabled, with
+-EFAULT if the userspace address is invalid or if no page table is
+present for the addresses (e.g. when using hugepages).
+
+4.108 KVM_S390_SET_CMMA_BITS
+
+Capability: KVM_CAP_S390_CMMA_MIGRATION
+Architectures: s390
+Type: vm ioctl
+Parameters: struct kvm_s390_cmma_log (in)
+Returns: 0 on success, a negative value on error
+
+This ioctl is used to set the values of the CMMA bits on the s390
+architecture. It is meant to be used during live migration to restore
+the CMMA values, but there are no restrictions on its use.
+The ioctl takes parameters via the kvm_s390_cmma_values struct.
+Each CMMA value takes up one byte.
+
+struct kvm_s390_cmma_log {
+       __u64 start_gfn;
+       __u32 count;
+       __u32 flags;
+       union {
+               __u64 remaining;
+               __u64 mask;
+       };
+       __u64 values;
+};
+
+start_gfn indicates the starting guest frame number,
+
+count indicates how many values are to be considered in the buffer,
+
+flags is not used and must be 0.
+
+mask indicates which PGSTE bits are to be considered.
+
+remaining is not used.
+
+values points to the buffer in userspace where to store the values.
+
+This ioctl can fail with -ENOMEM if not enough memory can be allocated to
+complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
+the count field is too large (e.g. more than KVM_S390_CMMA_SIZE_MAX) or
+if the flags field was not 0, with -EFAULT if the userspace address is
+invalid, if invalid pages are written to (e.g. after the end of memory)
+or if no page table is present for the addresses (e.g. when using
+hugepages).
+
+4.109 KVM_PPC_GET_CPU_CHAR
+
+Capability: KVM_CAP_PPC_GET_CPU_CHAR
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_ppc_cpu_char (out)
+Returns: 0 on successful completion
+        -EFAULT if struct kvm_ppc_cpu_char cannot be written
+
+This ioctl gives userspace information about certain characteristics
+of the CPU relating to speculative execution of instructions and
+possible information leakage resulting from speculative execution (see
+CVE-2017-5715, CVE-2017-5753 and CVE-2017-5754).  The information is
+returned in struct kvm_ppc_cpu_char, which looks like this:
+
+struct kvm_ppc_cpu_char {
+       __u64   character;              /* characteristics of the CPU */
+       __u64   behaviour;              /* recommended software behaviour */
+       __u64   character_mask;         /* valid bits in character */
+       __u64   behaviour_mask;         /* valid bits in behaviour */
+};
+
+For extensibility, the character_mask and behaviour_mask fields
+indicate which bits of character and behaviour have been filled in by
+the kernel.  If the set of defined bits is extended in future then
+userspace will be able to tell whether it is running on a kernel that
+knows about the new bits.
+
+The character field describes attributes of the CPU which can help
+with preventing inadvertent information disclosure - specifically,
+whether there is an instruction to flash-invalidate the L1 data cache
+(ori 30,30,0 or mtspr SPRN_TRIG2,rN), whether the L1 data cache is set
+to a mode where entries can only be used by the thread that created
+them, whether the bcctr[l] instruction prevents speculation, and
+whether a speculation barrier instruction (ori 31,31,0) is provided.
+
+The behaviour field describes actions that software should take to
+prevent inadvertent information disclosure, and thus describes which
+vulnerabilities the hardware is subject to; specifically whether the
+L1 data cache should be flushed when returning to user mode from the
+kernel, and whether a speculation barrier should be placed between an
+array bounds check and the array access.
+
+These fields use the same bit definitions as the new
+H_GET_CPU_CHARACTERISTICS hypercall.
+
+4.110 KVM_MEMORY_ENCRYPT_OP
+
+Capability: basic
+Architectures: x86
+Type: system
+Parameters: an opaque platform specific structure (in/out)
+Returns: 0 on success; -1 on error
+
+If the platform supports creating encrypted VMs then this ioctl can be used
+for issuing platform-specific memory encryption commands to manage those
+encrypted VMs.
+
+Currently, this ioctl is used for issuing Secure Encrypted Virtualization
+(SEV) commands on AMD Processors. The SEV commands are defined in
+Documentation/virt/kvm/amd-memory-encryption.rst.
+
+4.111 KVM_MEMORY_ENCRYPT_REG_REGION
+
+Capability: basic
+Architectures: x86
+Type: system
+Parameters: struct kvm_enc_region (in)
+Returns: 0 on success; -1 on error
+
+This ioctl can be used to register a guest memory region which may
+contain encrypted data (e.g. guest RAM, SMRAM etc).
+
+It is used in the SEV-enabled guest. When encryption is enabled, a guest
+memory region may contain encrypted data. The SEV memory encryption
+engine uses a tweak such that two identical plaintext pages, each at
+different locations will have differing ciphertexts. So swapping or
+moving ciphertext of those pages will not result in plaintext being
+swapped. So relocating (or migrating) physical backing pages for the SEV
+guest will require some additional steps.
+
+Note: The current SEV key management spec does not provide commands to
+swap or migrate (move) ciphertext pages. Hence, for now we pin the guest
+memory region registered with the ioctl.
+
+4.112 KVM_MEMORY_ENCRYPT_UNREG_REGION
+
+Capability: basic
+Architectures: x86
+Type: system
+Parameters: struct kvm_enc_region (in)
+Returns: 0 on success; -1 on error
+
+This ioctl can be used to unregister the guest memory region registered
+with KVM_MEMORY_ENCRYPT_REG_REGION ioctl above.
+
+4.113 KVM_HYPERV_EVENTFD
+
+Capability: KVM_CAP_HYPERV_EVENTFD
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_hyperv_eventfd (in)
+
+This ioctl (un)registers an eventfd to receive notifications from the guest on
+the specified Hyper-V connection id through the SIGNAL_EVENT hypercall, without
+causing a user exit.  SIGNAL_EVENT hypercall with non-zero event flag number
+(bits 24-31) still triggers a KVM_EXIT_HYPERV_HCALL user exit.
+
+struct kvm_hyperv_eventfd {
+       __u32 conn_id;
+       __s32 fd;
+       __u32 flags;
+       __u32 padding[3];
+};
+
+The conn_id field should fit within 24 bits:
+
+#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
+
+The acceptable values for the flags field are:
+
+#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
+
+Returns: 0 on success,
+       -EINVAL if conn_id or flags is outside the allowed range
+       -ENOENT on deassign if the conn_id isn't registered
+       -EEXIST on assign if the conn_id is already registered
+
+4.114 KVM_GET_NESTED_STATE
+
+Capability: KVM_CAP_NESTED_STATE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_nested_state (in/out)
+Returns: 0 on success, -1 on error
+Errors:
+  E2BIG:     the total state size exceeds the value of 'size' specified by
+             the user; the size required will be written into size.
+
+struct kvm_nested_state {
+       __u16 flags;
+       __u16 format;
+       __u32 size;
+
+       union {
+               struct kvm_vmx_nested_state_hdr vmx;
+               struct kvm_svm_nested_state_hdr svm;
+
+               /* Pad the header to 128 bytes.  */
+               __u8 pad[120];
+       } hdr;
+
+       union {
+               struct kvm_vmx_nested_state_data vmx[0];
+               struct kvm_svm_nested_state_data svm[0];
+       } data;
+};
+
+#define KVM_STATE_NESTED_GUEST_MODE    0x00000001
+#define KVM_STATE_NESTED_RUN_PENDING   0x00000002
+#define KVM_STATE_NESTED_EVMCS         0x00000004
+
+#define KVM_STATE_NESTED_FORMAT_VMX            0
+#define KVM_STATE_NESTED_FORMAT_SVM            1
+
+#define KVM_STATE_NESTED_VMX_VMCS_SIZE         0x1000
+
+#define KVM_STATE_NESTED_VMX_SMM_GUEST_MODE    0x00000001
+#define KVM_STATE_NESTED_VMX_SMM_VMXON         0x00000002
+
+struct kvm_vmx_nested_state_hdr {
+       __u64 vmxon_pa;
+       __u64 vmcs12_pa;
+
+       struct {
+               __u16 flags;
+       } smm;
+};
+
+struct kvm_vmx_nested_state_data {
+       __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
+       __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
+};
+
+This ioctl copies the vcpu's nested virtualization state from the kernel to
+userspace.
+
+The maximum size of the state can be retrieved by passing KVM_CAP_NESTED_STATE
+to the KVM_CHECK_EXTENSION ioctl().
+
+4.115 KVM_SET_NESTED_STATE
+
+Capability: KVM_CAP_NESTED_STATE
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_nested_state (in)
+Returns: 0 on success, -1 on error
+
+This copies the vcpu's kvm_nested_state struct from userspace to the kernel.
+For the definition of struct kvm_nested_state, see KVM_GET_NESTED_STATE.
+
+4.116 KVM_(UN)REGISTER_COALESCED_MMIO
+
+Capability: KVM_CAP_COALESCED_MMIO (for coalesced mmio)
+           KVM_CAP_COALESCED_PIO (for coalesced pio)
+Architectures: all
+Type: vm ioctl
+Parameters: struct kvm_coalesced_mmio_zone
+Returns: 0 on success, < 0 on error
+
+Coalesced I/O is a performance optimization that defers hardware
+register write emulation so that userspace exits are avoided.  It is
+typically used to reduce the overhead of emulating frequently accessed
+hardware registers.
+
+When a hardware register is configured for coalesced I/O, write accesses
+do not exit to userspace and their value is recorded in a ring buffer
+that is shared between kernel and userspace.
+
+Coalesced I/O is used if one or more write accesses to a hardware
+register can be deferred until a read or a write to another hardware
+register on the same device.  This last access will cause a vmexit and
+userspace will process accesses from the ring buffer before emulating
+it. That will avoid exiting to userspace on repeated writes.
+
+Coalesced pio is based on coalesced mmio. There is little difference
+between coalesced mmio and pio except that coalesced pio records accesses
+to I/O ports.
+
+4.117 KVM_CLEAR_DIRTY_LOG (vm ioctl)
+
+Capability: KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
+Architectures: x86, arm, arm64, mips
+Type: vm ioctl
+Parameters: struct kvm_dirty_log (in)
+Returns: 0 on success, -1 on error
+
+/* for KVM_CLEAR_DIRTY_LOG */
+struct kvm_clear_dirty_log {
+       __u32 slot;
+       __u32 num_pages;
+       __u64 first_page;
+       union {
+               void __user *dirty_bitmap; /* one bit per page */
+               __u64 padding;
+       };
+};
+
+The ioctl clears the dirty status of pages in a memory slot, according to
+the bitmap that is passed in struct kvm_clear_dirty_log's dirty_bitmap
+field.  Bit 0 of the bitmap corresponds to page "first_page" in the
+memory slot, and num_pages is the size in bits of the input bitmap.
+first_page must be a multiple of 64; num_pages must also be a multiple of
+64 unless first_page + num_pages is the size of the memory slot.  For each
+bit that is set in the input bitmap, the corresponding page is marked "clean"
+in KVM's dirty bitmap, and dirty tracking is re-enabled for that page
+(for example via write-protection, or by clearing the dirty bit in
+a page table entry).
+
+If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
+the address space for which you want to return the dirty bitmap.
+They must be less than the value that KVM_CHECK_EXTENSION returns for
+the KVM_CAP_MULTI_ADDRESS_SPACE capability.
+
+This ioctl is mostly useful when KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
+is enabled; for more information, see the description of the capability.
+However, it can always be used as long as KVM_CHECK_EXTENSION confirms
+that KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is present.
+
+4.118 KVM_GET_SUPPORTED_HV_CPUID
+
+Capability: KVM_CAP_HYPERV_CPUID
+Architectures: x86
+Type: vcpu ioctl
+Parameters: struct kvm_cpuid2 (in/out)
+Returns: 0 on success, -1 on error
+
+struct kvm_cpuid2 {
+       __u32 nent;
+       __u32 padding;
+       struct kvm_cpuid_entry2 entries[0];
+};
+
+struct kvm_cpuid_entry2 {
+       __u32 function;
+       __u32 index;
+       __u32 flags;
+       __u32 eax;
+       __u32 ebx;
+       __u32 ecx;
+       __u32 edx;
+       __u32 padding[3];
+};
+
+This ioctl returns x86 cpuid features leaves related to Hyper-V emulation in
+KVM.  Userspace can use the information returned by this ioctl to construct
+cpuid information presented to guests consuming Hyper-V enlightenments (e.g.
+Windows or Hyper-V guests).
+
+CPUID feature leaves returned by this ioctl are defined by Hyper-V Top Level
+Functional Specification (TLFS). These leaves can't be obtained with
+KVM_GET_SUPPORTED_CPUID ioctl because some of them intersect with KVM feature
+leaves (0x40000000, 0x40000001).
+
+Currently, the following list of CPUID leaves are returned:
+ HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS
+ HYPERV_CPUID_INTERFACE
+ HYPERV_CPUID_VERSION
+ HYPERV_CPUID_FEATURES
+ HYPERV_CPUID_ENLIGHTMENT_INFO
+ HYPERV_CPUID_IMPLEMENT_LIMITS
+ HYPERV_CPUID_NESTED_FEATURES
+
+HYPERV_CPUID_NESTED_FEATURES leaf is only exposed when Enlightened VMCS was
+enabled on the corresponding vCPU (KVM_CAP_HYPERV_ENLIGHTENED_VMCS).
+
+Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
+with the 'nent' field indicating the number of entries in the variable-size
+array 'entries'.  If the number of entries is too low to describe all Hyper-V
+feature leaves, an error (E2BIG) is returned. If the number is more or equal
+to the number of Hyper-V feature leaves, the 'nent' field is adjusted to the
+number of valid entries in the 'entries' array, which is then filled.
+
+'index' and 'flags' fields in 'struct kvm_cpuid_entry2' are currently reserved,
+userspace should not expect to get any particular value there.
+
+4.119 KVM_ARM_VCPU_FINALIZE
+
+Architectures: arm, arm64
+Type: vcpu ioctl
+Parameters: int feature (in)
+Returns: 0 on success, -1 on error
+Errors:
+  EPERM:     feature not enabled, needs configuration, or already finalized
+  EINVAL:    feature unknown or not present
+
+Recognised values for feature:
+  arm64      KVM_ARM_VCPU_SVE (requires KVM_CAP_ARM_SVE)
+
+Finalizes the configuration of the specified vcpu feature.
+
+The vcpu must already have been initialised, enabling the affected feature, by
+means of a successful KVM_ARM_VCPU_INIT call with the appropriate flag set in
+features[].
+
+For affected vcpu features, this is a mandatory step that must be performed
+before the vcpu is fully usable.
+
+Between KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE, the feature may be
+configured by use of ioctls such as KVM_SET_ONE_REG.  The exact configuration
+that should be performaned and how to do it are feature-dependent.
+
+Other calls that depend on a particular feature being finalized, such as
+KVM_RUN, KVM_GET_REG_LIST, KVM_GET_ONE_REG and KVM_SET_ONE_REG, will fail with
+-EPERM unless the feature has already been finalized by means of a
+KVM_ARM_VCPU_FINALIZE call.
+
+See KVM_ARM_VCPU_INIT for details of vcpu features that require finalization
+using this ioctl.
+
+4.120 KVM_SET_PMU_EVENT_FILTER
+
+Capability: KVM_CAP_PMU_EVENT_FILTER
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_pmu_event_filter (in)
+Returns: 0 on success, -1 on error
+
+struct kvm_pmu_event_filter {
+       __u32 action;
+       __u32 nevents;
+       __u32 fixed_counter_bitmap;
+       __u32 flags;
+       __u32 pad[4];
+       __u64 events[0];
+};
+
+This ioctl restricts the set of PMU events that the guest can program.
+The argument holds a list of events which will be allowed or denied.
+The eventsel+umask of each event the guest attempts to program is compared
+against the events field to determine whether the guest should have access.
+The events field only controls general purpose counters; fixed purpose
+counters are controlled by the fixed_counter_bitmap.
+
+No flags are defined yet, the field must be zero.
+
+Valid values for 'action':
+#define KVM_PMU_EVENT_ALLOW 0
+#define KVM_PMU_EVENT_DENY 1
+
+
+5. The kvm_run structure
+------------------------
+
+Application code obtains a pointer to the kvm_run structure by
+mmap()ing a vcpu fd.  From that point, application code can control
+execution by changing fields in kvm_run prior to calling the KVM_RUN
+ioctl, and obtain information about the reason KVM_RUN returned by
+looking up structure members.
+
+struct kvm_run {
+       /* in */
+       __u8 request_interrupt_window;
+
+Request that KVM_RUN return when it becomes possible to inject external
+interrupts into the guest.  Useful in conjunction with KVM_INTERRUPT.
+
+       __u8 immediate_exit;
+
+This field is polled once when KVM_RUN starts; if non-zero, KVM_RUN
+exits immediately, returning -EINTR.  In the common scenario where a
+signal is used to "kick" a VCPU out of KVM_RUN, this field can be used
+to avoid usage of KVM_SET_SIGNAL_MASK, which has worse scalability.
+Rather than blocking the signal outside KVM_RUN, userspace can set up
+a signal handler that sets run->immediate_exit to a non-zero value.
+
+This field is ignored if KVM_CAP_IMMEDIATE_EXIT is not available.
+
+       __u8 padding1[6];
+
+       /* out */
+       __u32 exit_reason;
+
+When KVM_RUN has returned successfully (return value 0), this informs
+application code why KVM_RUN has returned.  Allowable values for this
+field are detailed below.
+
+       __u8 ready_for_interrupt_injection;
+
+If request_interrupt_window has been specified, this field indicates
+an interrupt can be injected now with KVM_INTERRUPT.
+
+       __u8 if_flag;
+
+The value of the current interrupt flag.  Only valid if in-kernel
+local APIC is not used.
+
+       __u16 flags;
+
+More architecture-specific flags detailing state of the VCPU that may
+affect the device's behavior.  The only currently defined flag is
+KVM_RUN_X86_SMM, which is valid on x86 machines and is set if the
+VCPU is in system management mode.
+
+       /* in (pre_kvm_run), out (post_kvm_run) */
+       __u64 cr8;
+
+The value of the cr8 register.  Only valid if in-kernel local APIC is
+not used.  Both input and output.
+
+       __u64 apic_base;
+
+The value of the APIC BASE msr.  Only valid if in-kernel local
+APIC is not used.  Both input and output.
+
+       union {
+               /* KVM_EXIT_UNKNOWN */
+               struct {
+                       __u64 hardware_exit_reason;
+               } hw;
+
+If exit_reason is KVM_EXIT_UNKNOWN, the vcpu has exited due to unknown
+reasons.  Further architecture-specific information is available in
+hardware_exit_reason.
+
+               /* KVM_EXIT_FAIL_ENTRY */
+               struct {
+                       __u64 hardware_entry_failure_reason;
+               } fail_entry;
+
+If exit_reason is KVM_EXIT_FAIL_ENTRY, the vcpu could not be run due
+to unknown reasons.  Further architecture-specific information is
+available in hardware_entry_failure_reason.
+
+               /* KVM_EXIT_EXCEPTION */
+               struct {
+                       __u32 exception;
+                       __u32 error_code;
+               } ex;
+
+Unused.
+
+               /* KVM_EXIT_IO */
+               struct {
+#define KVM_EXIT_IO_IN  0
+#define KVM_EXIT_IO_OUT 1
+                       __u8 direction;
+                       __u8 size; /* bytes */
+                       __u16 port;
+                       __u32 count;
+                       __u64 data_offset; /* relative to kvm_run start */
+               } io;
+
+If exit_reason is KVM_EXIT_IO, then the vcpu has
+executed a port I/O instruction which could not be satisfied by kvm.
+data_offset describes where the data is located (KVM_EXIT_IO_OUT) or
+where kvm expects application code to place the data for the next
+KVM_RUN invocation (KVM_EXIT_IO_IN).  Data format is a packed array.
+
+               /* KVM_EXIT_DEBUG */
+               struct {
+                       struct kvm_debug_exit_arch arch;
+               } debug;
+
+If the exit_reason is KVM_EXIT_DEBUG, then a vcpu is processing a debug event
+for which architecture specific information is returned.
+
+               /* KVM_EXIT_MMIO */
+               struct {
+                       __u64 phys_addr;
+                       __u8  data[8];
+                       __u32 len;
+                       __u8  is_write;
+               } mmio;
+
+If exit_reason is KVM_EXIT_MMIO, then the vcpu has
+executed a memory-mapped I/O instruction which could not be satisfied
+by kvm.  The 'data' member contains the written data if 'is_write' is
+true, and should be filled by application code otherwise.
+
+The 'data' member contains, in its first 'len' bytes, the value as it would
+appear if the VCPU performed a load or store of the appropriate width directly
+to the byte array.
+
+NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR and
+      KVM_EXIT_EPR the corresponding
+operations are complete (and guest state is consistent) only after userspace
+has re-entered the kernel with KVM_RUN.  The kernel side will first finish
+incomplete operations and then check for pending signals.  Userspace
+can re-enter the guest with an unmasked signal pending to complete
+pending operations.
+
+               /* KVM_EXIT_HYPERCALL */
+               struct {
+                       __u64 nr;
+                       __u64 args[6];
+                       __u64 ret;
+                       __u32 longmode;
+                       __u32 pad;
+               } hypercall;
+
+Unused.  This was once used for 'hypercall to userspace'.  To implement
+such functionality, use KVM_EXIT_IO (x86) or KVM_EXIT_MMIO (all except s390).
+Note KVM_EXIT_IO is significantly faster than KVM_EXIT_MMIO.
+
+               /* KVM_EXIT_TPR_ACCESS */
+               struct {
+                       __u64 rip;
+                       __u32 is_write;
+                       __u32 pad;
+               } tpr_access;
+
+To be documented (KVM_TPR_ACCESS_REPORTING).
+
+               /* KVM_EXIT_S390_SIEIC */
+               struct {
+                       __u8 icptcode;
+                       __u64 mask; /* psw upper half */
+                       __u64 addr; /* psw lower half */
+                       __u16 ipa;
+                       __u32 ipb;
+               } s390_sieic;
+
+s390 specific.
+
+               /* KVM_EXIT_S390_RESET */
+#define KVM_S390_RESET_POR       1
+#define KVM_S390_RESET_CLEAR     2
+#define KVM_S390_RESET_SUBSYSTEM 4
+#define KVM_S390_RESET_CPU_INIT  8
+#define KVM_S390_RESET_IPL       16
+               __u64 s390_reset_flags;
+
+s390 specific.
+
+               /* KVM_EXIT_S390_UCONTROL */
+               struct {
+                       __u64 trans_exc_code;
+                       __u32 pgm_code;
+               } s390_ucontrol;
+
+s390 specific. A page fault has occurred for a user controlled virtual
+machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
+resolved by the kernel.
+The program code and the translation exception code that were placed
+in the cpu's lowcore are presented here as defined by the z Architecture
+Principles of Operation Book in the Chapter for Dynamic Address Translation
+(DAT)
+
+               /* KVM_EXIT_DCR */
+               struct {
+                       __u32 dcrn;
+                       __u32 data;
+                       __u8  is_write;
+               } dcr;
+
+Deprecated - was used for 440 KVM.
+
+               /* KVM_EXIT_OSI */
+               struct {
+                       __u64 gprs[32];
+               } osi;
+
+MOL uses a special hypercall interface it calls 'OSI'. To enable it, we catch
+hypercalls and exit with this exit struct that contains all the guest gprs.
+
+If exit_reason is KVM_EXIT_OSI, then the vcpu has triggered such a hypercall.
+Userspace can now handle the hypercall and when it's done modify the gprs as
+necessary. Upon guest entry all guest GPRs will then be replaced by the values
+in this struct.
+
+               /* KVM_EXIT_PAPR_HCALL */
+               struct {
+                       __u64 nr;
+                       __u64 ret;
+                       __u64 args[9];
+               } papr_hcall;
+
+This is used on 64-bit PowerPC when emulating a pSeries partition,
+e.g. with the 'pseries' machine type in qemu.  It occurs when the
+guest does a hypercall using the 'sc 1' instruction.  The 'nr' field
+contains the hypercall number (from the guest R3), and 'args' contains
+the arguments (from the guest R4 - R12).  Userspace should put the
+return code in 'ret' and any extra returned values in args[].
+The possible hypercalls are defined in the Power Architecture Platform
+Requirements (PAPR) document available from www.power.org (free
+developer registration required to access it).
+
+               /* KVM_EXIT_S390_TSCH */
+               struct {
+                       __u16 subchannel_id;
+                       __u16 subchannel_nr;
+                       __u32 io_int_parm;
+                       __u32 io_int_word;
+                       __u32 ipb;
+                       __u8 dequeued;
+               } s390_tsch;
+
+s390 specific. This exit occurs when KVM_CAP_S390_CSS_SUPPORT has been enabled
+and TEST SUBCHANNEL was intercepted. If dequeued is set, a pending I/O
+interrupt for the target subchannel has been dequeued and subchannel_id,
+subchannel_nr, io_int_parm and io_int_word contain the parameters for that
+interrupt. ipb is needed for instruction parameter decoding.
+
+               /* KVM_EXIT_EPR */
+               struct {
+                       __u32 epr;
+               } epr;
+
+On FSL BookE PowerPC chips, the interrupt controller has a fast patch
+interrupt acknowledge path to the core. When the core successfully
+delivers an interrupt, it automatically populates the EPR register with
+the interrupt vector number and acknowledges the interrupt inside
+the interrupt controller.
+
+In case the interrupt controller lives in user space, we need to do
+the interrupt acknowledge cycle through it to fetch the next to be
+delivered interrupt vector using this exit.
+
+It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an
+external interrupt has just been delivered into the guest. User space
+should put the acknowledged interrupt vector into the 'epr' field.
+
+               /* KVM_EXIT_SYSTEM_EVENT */
+               struct {
+#define KVM_SYSTEM_EVENT_SHUTDOWN       1
+#define KVM_SYSTEM_EVENT_RESET          2
+#define KVM_SYSTEM_EVENT_CRASH          3
+                       __u32 type;
+                       __u64 flags;
+               } system_event;
+
+If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered
+a system-level event using some architecture specific mechanism (hypercall
+or some special instruction). In case of ARM/ARM64, this is triggered using
+HVC instruction based PSCI call from the vcpu. The 'type' field describes
+the system-level event type. The 'flags' field describes architecture
+specific flags for the system-level event.
+
+Valid values for 'type' are:
+  KVM_SYSTEM_EVENT_SHUTDOWN -- the guest has requested a shutdown of the
+   VM. Userspace is not obliged to honour this, and if it does honour
+   this does not need to destroy the VM synchronously (ie it may call
+   KVM_RUN again before shutdown finally occurs).
+  KVM_SYSTEM_EVENT_RESET -- the guest has requested a reset of the VM.
+   As with SHUTDOWN, userspace can choose to ignore the request, or
+   to schedule the reset to occur in the future and may call KVM_RUN again.
+  KVM_SYSTEM_EVENT_CRASH -- the guest crash occurred and the guest
+   has requested a crash condition maintenance. Userspace can choose
+   to ignore the request, or to gather VM memory core dump and/or
+   reset/shutdown of the VM.
+
+               /* KVM_EXIT_IOAPIC_EOI */
+               struct {
+                       __u8 vector;
+               } eoi;
+
+Indicates that the VCPU's in-kernel local APIC received an EOI for a
+level-triggered IOAPIC interrupt.  This exit only triggers when the
+IOAPIC is implemented in userspace (i.e. KVM_CAP_SPLIT_IRQCHIP is enabled);
+the userspace IOAPIC should process the EOI and retrigger the interrupt if
+it is still asserted.  Vector is the LAPIC interrupt vector for which the
+EOI was received.
+
+               struct kvm_hyperv_exit {
+#define KVM_EXIT_HYPERV_SYNIC          1
+#define KVM_EXIT_HYPERV_HCALL          2
+                       __u32 type;
+                       union {
+                               struct {
+                                       __u32 msr;
+                                       __u64 control;
+                                       __u64 evt_page;
+                                       __u64 msg_page;
+                               } synic;
+                               struct {
+                                       __u64 input;
+                                       __u64 result;
+                                       __u64 params[2];
+                               } hcall;
+                       } u;
+               };
+               /* KVM_EXIT_HYPERV */
+                struct kvm_hyperv_exit hyperv;
+Indicates that the VCPU exits into userspace to process some tasks
+related to Hyper-V emulation.
+Valid values for 'type' are:
+       KVM_EXIT_HYPERV_SYNIC -- synchronously notify user-space about
+Hyper-V SynIC state change. Notification is used to remap SynIC
+event/message pages and to enable/disable SynIC messages/events processing
+in userspace.
+
+               /* Fix the size of the union. */
+               char padding[256];
+       };
+
+       /*
+        * shared registers between kvm and userspace.
+        * kvm_valid_regs specifies the register classes set by the host
+        * kvm_dirty_regs specified the register classes dirtied by userspace
+        * struct kvm_sync_regs is architecture specific, as well as the
+        * bits for kvm_valid_regs and kvm_dirty_regs
+        */
+       __u64 kvm_valid_regs;
+       __u64 kvm_dirty_regs;
+       union {
+               struct kvm_sync_regs regs;
+               char padding[SYNC_REGS_SIZE_BYTES];
+       } s;
+
+If KVM_CAP_SYNC_REGS is defined, these fields allow userspace to access
+certain guest registers without having to call SET/GET_*REGS. Thus we can
+avoid some system call overhead if userspace has to handle the exit.
+Userspace can query the validity of the structure by checking
+kvm_valid_regs for specific bits. These bits are architecture specific
+and usually define the validity of a groups of registers. (e.g. one bit
+ for general purpose registers)
+
+Please note that the kernel is allowed to use the kvm_run structure as the
+primary storage for certain register types. Therefore, the kernel may use the
+values in kvm_run even if the corresponding bit in kvm_dirty_regs is not set.
+
+};
+
+
+
+6. Capabilities that can be enabled on vCPUs
+--------------------------------------------
+
+There are certain capabilities that change the behavior of the virtual CPU or
+the virtual machine when enabled. To enable them, please see section 4.37.
+Below you can find a list of capabilities and what their effect on the vCPU or
+the virtual machine is when enabling them.
+
+The following information is provided along with the description:
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Target: whether this is a per-vcpu or per-vm capability.
+
+  Parameters: what parameters are accepted by the capability.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+
+6.1 KVM_CAP_PPC_OSI
+
+Architectures: ppc
+Target: vcpu
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of OSI hypercalls that otherwise would
+be treated as normal system calls to be injected into the guest. OSI hypercalls
+were invented by Mac-on-Linux to have a standardized communication mechanism
+between the guest and the host.
+
+When this capability is enabled, KVM_EXIT_OSI can occur.
+
+
+6.2 KVM_CAP_PPC_PAPR
+
+Architectures: ppc
+Target: vcpu
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables interception of PAPR hypercalls. PAPR hypercalls are
+done using the hypercall instruction "sc 1".
+
+It also sets the guest privilege level to "supervisor" mode. Usually the guest
+runs in "hypervisor" privilege mode with a few missing features.
+
+In addition to the above, it changes the semantics of SDR1. In this mode, the
+HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
+HTAB invisible to the guest.
+
+When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
+
+
+6.3 KVM_CAP_SW_TLB
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] is the address of a struct kvm_config_tlb
+Returns: 0 on success; -1 on error
+
+struct kvm_config_tlb {
+       __u64 params;
+       __u64 array;
+       __u32 mmu_type;
+       __u32 array_len;
+};
+
+Configures the virtual CPU's TLB array, establishing a shared memory area
+between userspace and KVM.  The "params" and "array" fields are userspace
+addresses of mmu-type-specific data structures.  The "array_len" field is an
+safety mechanism, and should be set to the size in bytes of the memory that
+userspace has reserved for the array.  It must be at least the size dictated
+by "mmu_type" and "params".
+
+While KVM_RUN is active, the shared region is under control of KVM.  Its
+contents are undefined, and any modification by userspace results in
+boundedly undefined behavior.
+
+On return from KVM_RUN, the shared region will reflect the current state of
+the guest's TLB.  If userspace makes any changes, it must call KVM_DIRTY_TLB
+to tell KVM which entries have been changed, prior to calling KVM_RUN again
+on this vcpu.
+
+For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
+ - The "params" field is of type "struct kvm_book3e_206_tlb_params".
+ - The "array" field points to an array of type "struct
+   kvm_book3e_206_tlb_entry".
+ - The array consists of all entries in the first TLB, followed by all
+   entries in the second TLB.
+ - Within a TLB, entries are ordered first by increasing set number.  Within a
+   set, entries are ordered by way (increasing ESEL).
+ - The hash for determining set number in TLB0 is: (MAS2 >> 12) & (num_sets - 1)
+   where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
+ - The tsize field of mas1 shall be set to 4K on TLB0, even though the
+   hardware ignores this value for TLB0.
+
+6.4 KVM_CAP_S390_CSS_SUPPORT
+
+Architectures: s390
+Target: vcpu
+Parameters: none
+Returns: 0 on success; -1 on error
+
+This capability enables support for handling of channel I/O instructions.
+
+TEST PENDING INTERRUPTION and the interrupt portion of TEST SUBCHANNEL are
+handled in-kernel, while the other I/O instructions are passed to userspace.
+
+When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
+SUBCHANNEL intercepts.
+
+Note that even though this capability is enabled per-vcpu, the complete
+virtual machine is affected.
+
+6.5 KVM_CAP_PPC_EPR
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] defines whether the proxy facility is active
+Returns: 0 on success; -1 on error
+
+This capability enables or disables the delivery of interrupts through the
+external proxy facility.
+
+When enabled (args[0] != 0), every time the guest gets an external interrupt
+delivered, it automatically exits into user space with a KVM_EXIT_EPR exit
+to receive the topmost interrupt vector.
+
+When disabled (args[0] == 0), behavior is as if this facility is unsupported.
+
+When this capability is enabled, KVM_EXIT_EPR can occur.
+
+6.6 KVM_CAP_IRQ_MPIC
+
+Architectures: ppc
+Parameters: args[0] is the MPIC device fd
+            args[1] is the MPIC CPU number for this vcpu
+
+This capability connects the vcpu to an in-kernel MPIC device.
+
+6.7 KVM_CAP_IRQ_XICS
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] is the XICS device fd
+            args[1] is the XICS CPU number (server ID) for this vcpu
+
+This capability connects the vcpu to an in-kernel XICS device.
+
+6.8 KVM_CAP_S390_IRQCHIP
+
+Architectures: s390
+Target: vm
+Parameters: none
+
+This capability enables the in-kernel irqchip for s390. Please refer to
+"4.24 KVM_CREATE_IRQCHIP" for details.
+
+6.9 KVM_CAP_MIPS_FPU
+
+Architectures: mips
+Target: vcpu
+Parameters: args[0] is reserved for future use (should be 0).
+
+This capability allows the use of the host Floating Point Unit by the guest. It
+allows the Config1.FP bit to be set to enable the FPU in the guest. Once this is
+done the KVM_REG_MIPS_FPR_* and KVM_REG_MIPS_FCR_* registers can be accessed
+(depending on the current guest FPU register mode), and the Status.FR,
+Config5.FRE bits are accessible via the KVM API and also from the guest,
+depending on them being supported by the FPU.
+
+6.10 KVM_CAP_MIPS_MSA
+
+Architectures: mips
+Target: vcpu
+Parameters: args[0] is reserved for future use (should be 0).
+
+This capability allows the use of the MIPS SIMD Architecture (MSA) by the guest.
+It allows the Config3.MSAP bit to be set to enable the use of MSA by the guest.
+Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
+accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
+the guest.
+
+6.74 KVM_CAP_SYNC_REGS
+Architectures: s390, x86
+Target: s390: always enabled, x86: vcpu
+Parameters: none
+Returns: x86: KVM_CHECK_EXTENSION returns a bit-array indicating which register
+sets are supported (bitfields defined in arch/x86/include/uapi/asm/kvm.h).
+
+As described above in the kvm_sync_regs struct info in section 5 (kvm_run):
+KVM_CAP_SYNC_REGS "allow[s] userspace to access certain guest registers
+without having to call SET/GET_*REGS". This reduces overhead by eliminating
+repeated ioctl calls for setting and/or getting register values. This is
+particularly important when userspace is making synchronous guest state
+modifications, e.g. when emulating and/or intercepting instructions in
+userspace.
+
+For s390 specifics, please refer to the source code.
+
+For x86:
+- the register sets to be copied out to kvm_run are selectable
+  by userspace (rather that all sets being copied out for every exit).
+- vcpu_events are available in addition to regs and sregs.
+
+For x86, the 'kvm_valid_regs' field of struct kvm_run is overloaded to
+function as an input bit-array field set by userspace to indicate the
+specific register sets to be copied out on the next exit.
+
+To indicate when userspace has modified values that should be copied into
+the vCPU, the all architecture bitarray field, 'kvm_dirty_regs' must be set.
+This is done using the same bitflags as for the 'kvm_valid_regs' field.
+If the dirty bit is not set, then the register set values will not be copied
+into the vCPU even if they've been modified.
+
+Unused bitfields in the bitarrays must be set to zero.
+
+struct kvm_sync_regs {
+        struct kvm_regs regs;
+        struct kvm_sregs sregs;
+        struct kvm_vcpu_events events;
+};
+
+6.75 KVM_CAP_PPC_IRQ_XIVE
+
+Architectures: ppc
+Target: vcpu
+Parameters: args[0] is the XIVE device fd
+            args[1] is the XIVE CPU number (server ID) for this vcpu
+
+This capability connects the vcpu to an in-kernel XIVE device.
+
+7. Capabilities that can be enabled on VMs
+------------------------------------------
+
+There are certain capabilities that change the behavior of the virtual
+machine when enabled. To enable them, please see section 4.37. Below
+you can find a list of capabilities and what their effect on the VM
+is when enabling them.
+
+The following information is provided along with the description:
+
+  Architectures: which instruction set architectures provide this ioctl.
+      x86 includes both i386 and x86_64.
+
+  Parameters: what parameters are accepted by the capability.
+
+  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
+      are not detailed, but errors with specific meanings are.
+
+
+7.1 KVM_CAP_PPC_ENABLE_HCALL
+
+Architectures: ppc
+Parameters: args[0] is the sPAPR hcall number
+           args[1] is 0 to disable, 1 to enable in-kernel handling
+
+This capability controls whether individual sPAPR hypercalls (hcalls)
+get handled by the kernel or not.  Enabling or disabling in-kernel
+handling of an hcall is effective across the VM.  On creation, an
+initial set of hcalls are enabled for in-kernel handling, which
+consists of those hcalls for which in-kernel handlers were implemented
+before this capability was implemented.  If disabled, the kernel will
+not to attempt to handle the hcall, but will always exit to userspace
+to handle it.  Note that it may not make sense to enable some and
+disable others of a group of related hcalls, but KVM does not prevent
+userspace from doing that.
+
+If the hcall number specified is not one that has an in-kernel
+implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL
+error.
+
+7.2 KVM_CAP_S390_USER_SIGP
+
+Architectures: s390
+Parameters: none
+
+This capability controls which SIGP orders will be handled completely in user
+space. With this capability enabled, all fast orders will be handled completely
+in the kernel:
+- SENSE
+- SENSE RUNNING
+- EXTERNAL CALL
+- EMERGENCY SIGNAL
+- CONDITIONAL EMERGENCY SIGNAL
+
+All other orders will be handled completely in user space.
+
+Only privileged operation exceptions will be checked for in the kernel (or even
+in the hardware prior to interception). If this capability is not enabled, the
+old way of handling SIGP orders is used (partially in kernel and user space).
+
+7.3 KVM_CAP_S390_VECTOR_REGISTERS
+
+Architectures: s390
+Parameters: none
+Returns: 0 on success, negative value on error
+
+Allows use of the vector registers introduced with z13 processor, and
+provides for the synchronization between host and user space.  Will
+return -EINVAL if the machine does not support vectors.
+
+7.4 KVM_CAP_S390_USER_STSI
+
+Architectures: s390
+Parameters: none
+
+This capability allows post-handlers for the STSI instruction. After
+initial handling in the kernel, KVM exits to user space with
+KVM_EXIT_S390_STSI to allow user space to insert further data.
+
+Before exiting to userspace, kvm handlers should fill in s390_stsi field of
+vcpu->run:
+struct {
+       __u64 addr;
+       __u8 ar;
+       __u8 reserved;
+       __u8 fc;
+       __u8 sel1;
+       __u16 sel2;
+} s390_stsi;
+
+@addr - guest address of STSI SYSIB
+@fc   - function code
+@sel1 - selector 1
+@sel2 - selector 2
+@ar   - access register number
+
+KVM handlers should exit to userspace with rc = -EREMOTE.
+
+7.5 KVM_CAP_SPLIT_IRQCHIP
+
+Architectures: x86
+Parameters: args[0] - number of routes reserved for userspace IOAPICs
+Returns: 0 on success, -1 on error
+
+Create a local apic for each processor in the kernel. This can be used
+instead of KVM_CREATE_IRQCHIP if the userspace VMM wishes to emulate the
+IOAPIC and PIC (and also the PIT, even though this has to be enabled
+separately).
+
+This capability also enables in kernel routing of interrupt requests;
+when KVM_CAP_SPLIT_IRQCHIP only routes of KVM_IRQ_ROUTING_MSI type are
+used in the IRQ routing table.  The first args[0] MSI routes are reserved
+for the IOAPIC pins.  Whenever the LAPIC receives an EOI for these routes,
+a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace.
+
+Fails if VCPU has already been created, or if the irqchip is already in the
+kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
+
+7.6 KVM_CAP_S390_RI
+
+Architectures: s390
+Parameters: none
+
+Allows use of runtime-instrumentation introduced with zEC12 processor.
+Will return -EINVAL if the machine does not support runtime-instrumentation.
+Will return -EBUSY if a VCPU has already been created.
+
+7.7 KVM_CAP_X2APIC_API
+
+Architectures: x86
+Parameters: args[0] - features that should be enabled
+Returns: 0 on success, -EINVAL when args[0] contains invalid features
+
+Valid feature flags in args[0] are
+
+#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
+#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
+
+Enabling KVM_X2APIC_API_USE_32BIT_IDS changes the behavior of
+KVM_SET_GSI_ROUTING, KVM_SIGNAL_MSI, KVM_SET_LAPIC, and KVM_GET_LAPIC,
+allowing the use of 32-bit APIC IDs.  See KVM_CAP_X2APIC_API in their
+respective sections.
+
+KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK must be enabled for x2APIC to work
+in logical mode or with more than 255 VCPUs.  Otherwise, KVM treats 0xff
+as a broadcast even in x2APIC mode in order to support physical x2APIC
+without interrupt remapping.  This is undesirable in logical mode,
+where 0xff represents CPUs 0-7 in cluster 0.
+
+7.8 KVM_CAP_S390_USER_INSTR0
+
+Architectures: s390
+Parameters: none
+
+With this capability enabled, all illegal instructions 0x0000 (2 bytes) will
+be intercepted and forwarded to user space. User space can use this
+mechanism e.g. to realize 2-byte software breakpoints. The kernel will
+not inject an operating exception for these instructions, user space has
+to take care of that.
+
+This capability can be enabled dynamically even if VCPUs were already
+created and are running.
+
+7.9 KVM_CAP_S390_GS
+
+Architectures: s390
+Parameters: none
+Returns: 0 on success; -EINVAL if the machine does not support
+        guarded storage; -EBUSY if a VCPU has already been created.
+
+Allows use of guarded storage for the KVM guest.
+
+7.10 KVM_CAP_S390_AIS
+
+Architectures: s390
+Parameters: none
+
+Allow use of adapter-interruption suppression.
+Returns: 0 on success; -EBUSY if a VCPU has already been created.
+
+7.11 KVM_CAP_PPC_SMT
+
+Architectures: ppc
+Parameters: vsmt_mode, flags
+
+Enabling this capability on a VM provides userspace with a way to set
+the desired virtual SMT mode (i.e. the number of virtual CPUs per
+virtual core).  The virtual SMT mode, vsmt_mode, must be a power of 2
+between 1 and 8.  On POWER8, vsmt_mode must also be no greater than
+the number of threads per subcore for the host.  Currently flags must
+be 0.  A successful call to enable this capability will result in
+vsmt_mode being returned when the KVM_CAP_PPC_SMT capability is
+subsequently queried for the VM.  This capability is only supported by
+HV KVM, and can only be set before any VCPUs have been created.
+The KVM_CAP_PPC_SMT_POSSIBLE capability indicates which virtual SMT
+modes are available.
+
+7.12 KVM_CAP_PPC_FWNMI
+
+Architectures: ppc
+Parameters: none
+
+With this capability a machine check exception in the guest address
+space will cause KVM to exit the guest with NMI exit reason. This
+enables QEMU to build error log and branch to guest kernel registered
+machine check handling routine. Without this capability KVM will
+branch to guests' 0x200 interrupt vector.
+
+7.13 KVM_CAP_X86_DISABLE_EXITS
+
+Architectures: x86
+Parameters: args[0] defines which exits are disabled
+Returns: 0 on success, -EINVAL when args[0] contains invalid exits
+
+Valid bits in args[0] are
+
+#define KVM_X86_DISABLE_EXITS_MWAIT            (1 << 0)
+#define KVM_X86_DISABLE_EXITS_HLT              (1 << 1)
+#define KVM_X86_DISABLE_EXITS_PAUSE            (1 << 2)
+#define KVM_X86_DISABLE_EXITS_CSTATE           (1 << 3)
+
+Enabling this capability on a VM provides userspace with a way to no
+longer intercept some instructions for improved latency in some
+workloads, and is suggested when vCPUs are associated to dedicated
+physical CPUs.  More bits can be added in the future; userspace can
+just pass the KVM_CHECK_EXTENSION result to KVM_ENABLE_CAP to disable
+all such vmexits.
+
+Do not enable KVM_FEATURE_PV_UNHALT if you disable HLT exits.
+
+7.14 KVM_CAP_S390_HPAGE_1M
+
+Architectures: s390
+Parameters: none
+Returns: 0 on success, -EINVAL if hpage module parameter was not set
+        or cmma is enabled, or the VM has the KVM_VM_S390_UCONTROL
+        flag set
+
+With this capability the KVM support for memory backing with 1m pages
+through hugetlbfs can be enabled for a VM. After the capability is
+enabled, cmma can't be enabled anymore and pfmfi and the storage key
+interpretation are disabled. If cmma has already been enabled or the
+hpage module parameter is not set to 1, -EINVAL is returned.
+
+While it is generally possible to create a huge page backed VM without
+this capability, the VM will not be able to run.
+
+7.15 KVM_CAP_MSR_PLATFORM_INFO
+
+Architectures: x86
+Parameters: args[0] whether feature should be enabled or not
+
+With this capability, a guest may read the MSR_PLATFORM_INFO MSR. Otherwise,
+a #GP would be raised when the guest tries to access. Currently, this
+capability does not enable write permissions of this MSR for the guest.
+
+7.16 KVM_CAP_PPC_NESTED_HV
+
+Architectures: ppc
+Parameters: none
+Returns: 0 on success, -EINVAL when the implementation doesn't support
+        nested-HV virtualization.
+
+HV-KVM on POWER9 and later systems allows for "nested-HV"
+virtualization, which provides a way for a guest VM to run guests that
+can run using the CPU's supervisor mode (privileged non-hypervisor
+state).  Enabling this capability on a VM depends on the CPU having
+the necessary functionality and on the facility being enabled with a
+kvm-hv module parameter.
+
+7.17 KVM_CAP_EXCEPTION_PAYLOAD
+
+Architectures: x86
+Parameters: args[0] whether feature should be enabled or not
+
+With this capability enabled, CR2 will not be modified prior to the
+emulated VM-exit when L1 intercepts a #PF exception that occurs in
+L2. Similarly, for kvm-intel only, DR6 will not be modified prior to
+the emulated VM-exit when L1 intercepts a #DB exception that occurs in
+L2. As a result, when KVM_GET_VCPU_EVENTS reports a pending #PF (or
+#DB) exception for L2, exception.has_payload will be set and the
+faulting address (or the new DR6 bits*) will be reported in the
+exception_payload field. Similarly, when userspace injects a #PF (or
+#DB) into L2 using KVM_SET_VCPU_EVENTS, it is expected to set
+exception.has_payload and to put the faulting address (or the new DR6
+bits*) in the exception_payload field.
+
+This capability also enables exception.pending in struct
+kvm_vcpu_events, which allows userspace to distinguish between pending
+and injected exceptions.
+
+
+* For the new DR6 bits, note that bit 16 is set iff the #DB exception
+  will clear DR6.RTM.
+
+7.18 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
+
+Architectures: x86, arm, arm64, mips
+Parameters: args[0] whether feature should be enabled or not
+
+With this capability enabled, KVM_GET_DIRTY_LOG will not automatically
+clear and write-protect all pages that are returned as dirty.
+Rather, userspace will have to do this operation separately using
+KVM_CLEAR_DIRTY_LOG.
+
+At the cost of a slightly more complicated operation, this provides better
+scalability and responsiveness for two reasons.  First,
+KVM_CLEAR_DIRTY_LOG ioctl can operate on a 64-page granularity rather
+than requiring to sync a full memslot; this ensures that KVM does not
+take spinlocks for an extended period of time.  Second, in some cases a
+large amount of time can pass between a call to KVM_GET_DIRTY_LOG and
+userspace actually using the data in the page.  Pages can be modified
+during this time, which is inefficint for both the guest and userspace:
+the guest will incur a higher penalty due to write protection faults,
+while userspace can see false reports of dirty pages.  Manual reprotection
+helps reducing this time, improving guest performance and reducing the
+number of dirty log false positives.
+
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make
+it hard or impossible to use it correctly.  The availability of
+KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 signals that those bugs are fixed.
+Userspace should not try to use KVM_CAP_MANUAL_DIRTY_LOG_PROTECT.
+
+8. Other capabilities.
+----------------------
+
+This section lists capabilities that give information about other
+features of the KVM implementation.
+
+8.1 KVM_CAP_PPC_HWRNG
+
+Architectures: ppc
+
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel has an implementation of the
+H_RANDOM hypercall backed by a hardware random-number generator.
+If present, the kernel H_RANDOM handler can be enabled for guest use
+with the KVM_CAP_PPC_ENABLE_HCALL capability.
+
+8.2 KVM_CAP_HYPERV_SYNIC
+
+Architectures: x86
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel has an implementation of the
+Hyper-V Synthetic interrupt controller(SynIC). Hyper-V SynIC is
+used to support Windows Hyper-V based guest paravirt drivers(VMBus).
+
+In order to use SynIC, it has to be activated by setting this
+capability via KVM_ENABLE_CAP ioctl on the vcpu fd. Note that this
+will disable the use of APIC hardware virtualization even if supported
+by the CPU, as it's incompatible with SynIC auto-EOI behavior.
+
+8.3 KVM_CAP_PPC_RADIX_MMU
+
+Architectures: ppc
+
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel can support guests using the
+radix MMU defined in Power ISA V3.00 (as implemented in the POWER9
+processor).
+
+8.4 KVM_CAP_PPC_HASH_MMU_V3
+
+Architectures: ppc
+
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel can support guests using the
+hashed page table MMU defined in Power ISA V3.00 (as implemented in
+the POWER9 processor), including in-memory segment tables.
+
+8.5 KVM_CAP_MIPS_VZ
+
+Architectures: mips
+
+This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
+it is available, means that full hardware assisted virtualization capabilities
+of the hardware are available for use through KVM. An appropriate
+KVM_VM_MIPS_* type must be passed to KVM_CREATE_VM to create a VM which
+utilises it.
+
+If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
+available, it means that the VM is using full hardware assisted virtualization
+capabilities of the hardware. This is useful to check after creating a VM with
+KVM_VM_MIPS_DEFAULT.
+
+The value returned by KVM_CHECK_EXTENSION should be compared against known
+values (see below). All other values are reserved. This is to allow for the
+possibility of other hardware assisted virtualization implementations which
+may be incompatible with the MIPS VZ ASE.
+
+ 0: The trap & emulate implementation is in use to run guest code in user
+    mode. Guest virtual memory segments are rearranged to fit the guest in the
+    user mode address space.
+
+ 1: The MIPS VZ ASE is in use, providing full hardware assisted
+    virtualization, including standard guest virtual memory segments.
+
+8.6 KVM_CAP_MIPS_TE
+
+Architectures: mips
+
+This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
+it is available, means that the trap & emulate implementation is available to
+run guest code in user mode, even if KVM_CAP_MIPS_VZ indicates that hardware
+assisted virtualisation is also available. KVM_VM_MIPS_TE (0) must be passed
+to KVM_CREATE_VM to create a VM which utilises it.
+
+If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
+available, it means that the VM is using trap & emulate.
+
+8.7 KVM_CAP_MIPS_64BIT
+
+Architectures: mips
+
+This capability indicates the supported architecture type of the guest, i.e. the
+supported register and address width.
+
+The values returned when this capability is checked by KVM_CHECK_EXTENSION on a
+kvm VM handle correspond roughly to the CP0_Config.AT register field, and should
+be checked specifically against known values (see below). All other values are
+reserved.
+
+ 0: MIPS32 or microMIPS32.
+    Both registers and addresses are 32-bits wide.
+    It will only be possible to run 32-bit guest code.
+
+ 1: MIPS64 or microMIPS64 with access only to 32-bit compatibility segments.
+    Registers are 64-bits wide, but addresses are 32-bits wide.
+    64-bit guest code may run but cannot access MIPS64 memory segments.
+    It will also be possible to run 32-bit guest code.
+
+ 2: MIPS64 or microMIPS64 with access to all address segments.
+    Both registers and addresses are 64-bits wide.
+    It will be possible to run 64-bit or 32-bit guest code.
+
+8.9 KVM_CAP_ARM_USER_IRQ
+
+Architectures: arm, arm64
+This capability, if KVM_CHECK_EXTENSION indicates that it is available, means
+that if userspace creates a VM without an in-kernel interrupt controller, it
+will be notified of changes to the output level of in-kernel emulated devices,
+which can generate virtual interrupts, presented to the VM.
+For such VMs, on every return to userspace, the kernel
+updates the vcpu's run->s.regs.device_irq_level field to represent the actual
+output level of the device.
+
+Whenever kvm detects a change in the device output level, kvm guarantees at
+least one return to userspace before running the VM.  This exit could either
+be a KVM_EXIT_INTR or any other exit event, like KVM_EXIT_MMIO. This way,
+userspace can always sample the device output level and re-compute the state of
+the userspace interrupt controller.  Userspace should always check the state
+of run->s.regs.device_irq_level on every kvm exit.
+The value in run->s.regs.device_irq_level can represent both level and edge
+triggered interrupt signals, depending on the device.  Edge triggered interrupt
+signals will exit to userspace with the bit in run->s.regs.device_irq_level
+set exactly once per edge signal.
+
+The field run->s.regs.device_irq_level is available independent of
+run->kvm_valid_regs or run->kvm_dirty_regs bits.
+
+If KVM_CAP_ARM_USER_IRQ is supported, the KVM_CHECK_EXTENSION ioctl returns a
+number larger than 0 indicating the version of this capability is implemented
+and thereby which bits in in run->s.regs.device_irq_level can signal values.
+
+Currently the following bits are defined for the device_irq_level bitmap:
+
+  KVM_CAP_ARM_USER_IRQ >= 1:
+
+    KVM_ARM_DEV_EL1_VTIMER -  EL1 virtual timer
+    KVM_ARM_DEV_EL1_PTIMER -  EL1 physical timer
+    KVM_ARM_DEV_PMU        -  ARM PMU overflow interrupt signal
+
+Future versions of kvm may implement additional events. These will get
+indicated by returning a higher number from KVM_CHECK_EXTENSION and will be
+listed above.
+
+8.10 KVM_CAP_PPC_SMT_POSSIBLE
+
+Architectures: ppc
+
+Querying this capability returns a bitmap indicating the possible
+virtual SMT modes that can be set using KVM_CAP_PPC_SMT.  If bit N
+(counting from the right) is set, then a virtual SMT mode of 2^N is
+available.
+
+8.11 KVM_CAP_HYPERV_SYNIC2
+
+Architectures: x86
+
+This capability enables a newer version of Hyper-V Synthetic interrupt
+controller (SynIC).  The only difference with KVM_CAP_HYPERV_SYNIC is that KVM
+doesn't clear SynIC message and event flags pages when they are enabled by
+writing to the respective MSRs.
+
+8.12 KVM_CAP_HYPERV_VP_INDEX
+
+Architectures: x86
+
+This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr.  Its
+value is used to denote the target vcpu for a SynIC interrupt.  For
+compatibilty, KVM initializes this msr to KVM's internal vcpu index.  When this
+capability is absent, userspace can still query this msr's value.
+
+8.13 KVM_CAP_S390_AIS_MIGRATION
+
+Architectures: s390
+Parameters: none
+
+This capability indicates if the flic device will be able to get/set the
+AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows
+to discover this without having to create a flic device.
+
+8.14 KVM_CAP_S390_PSW
+
+Architectures: s390
+
+This capability indicates that the PSW is exposed via the kvm_run structure.
+
+8.15 KVM_CAP_S390_GMAP
+
+Architectures: s390
+
+This capability indicates that the user space memory used as guest mapping can
+be anywhere in the user memory address space, as long as the memory slots are
+aligned and sized to a segment (1MB) boundary.
+
+8.16 KVM_CAP_S390_COW
+
+Architectures: s390
+
+This capability indicates that the user space memory used as guest mapping can
+use copy-on-write semantics as well as dirty pages tracking via read-only page
+tables.
+
+8.17 KVM_CAP_S390_BPB
+
+Architectures: s390
+
+This capability indicates that kvm will implement the interfaces to handle
+reset, migration and nested KVM for branch prediction blocking. The stfle
+facility 82 should not be provided to the guest without this capability.
+
+8.18 KVM_CAP_HYPERV_TLBFLUSH
+
+Architectures: x86
+
+This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush
+hypercalls:
+HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx,
+HvFlushVirtualAddressList, HvFlushVirtualAddressListEx.
+
+8.19 KVM_CAP_ARM_INJECT_SERROR_ESR
+
+Architectures: arm, arm64
+
+This capability indicates that userspace can specify (via the
+KVM_SET_VCPU_EVENTS ioctl) the syndrome value reported to the guest when it
+takes a virtual SError interrupt exception.
+If KVM advertises this capability, userspace can only specify the ISS field for
+the ESR syndrome. Other parts of the ESR, such as the EC are generated by the
+CPU when the exception is taken. If this virtual SError is taken to EL1 using
+AArch64, this value will be reported in the ISS field of ESR_ELx.
+
+See KVM_CAP_VCPU_EVENTS for more details.
+8.20 KVM_CAP_HYPERV_SEND_IPI
+
+Architectures: x86
+
+This capability indicates that KVM supports paravirtualized Hyper-V IPI send
+hypercalls:
+HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx.
diff --git a/Documentation/virt/kvm/arm/hyp-abi.txt b/Documentation/virt/kvm/arm/hyp-abi.txt
new file mode 100644 (file)
index 0000000..a20a0be
--- /dev/null
@@ -0,0 +1,53 @@
+* Internal ABI between the kernel and HYP
+
+This file documents the interaction between the Linux kernel and the
+hypervisor layer when running Linux as a hypervisor (for example
+KVM). It doesn't cover the interaction of the kernel with the
+hypervisor when running as a guest (under Xen, KVM or any other
+hypervisor), or any hypervisor-specific interaction when the kernel is
+used as a host.
+
+On arm and arm64 (without VHE), the kernel doesn't run in hypervisor
+mode, but still needs to interact with it, allowing a built-in
+hypervisor to be either installed or torn down.
+
+In order to achieve this, the kernel must be booted at HYP (arm) or
+EL2 (arm64), allowing it to install a set of stubs before dropping to
+SVC/EL1. These stubs are accessible by using a 'hvc #0' instruction,
+and only act on individual CPUs.
+
+Unless specified otherwise, any built-in hypervisor must implement
+these functions (see arch/arm{,64}/include/asm/virt.h):
+
+* r0/x0 = HVC_SET_VECTORS
+  r1/x1 = vectors
+
+  Set HVBAR/VBAR_EL2 to 'vectors' to enable a hypervisor. 'vectors'
+  must be a physical address, and respect the alignment requirements
+  of the architecture. Only implemented by the initial stubs, not by
+  Linux hypervisors.
+
+* r0/x0 = HVC_RESET_VECTORS
+
+  Turn HYP/EL2 MMU off, and reset HVBAR/VBAR_EL2 to the initials
+  stubs' exception vector value. This effectively disables an existing
+  hypervisor.
+
+* r0/x0 = HVC_SOFT_RESTART
+  r1/x1 = restart address
+  x2 = x0's value when entering the next payload (arm64)
+  x3 = x1's value when entering the next payload (arm64)
+  x4 = x2's value when entering the next payload (arm64)
+
+  Mask all exceptions, disable the MMU, move the arguments into place
+  (arm64 only), and jump to the restart address while at HYP/EL2. This
+  hypercall is not expected to return to its caller.
+
+Any other value of r0/x0 triggers a hypervisor-specific handling,
+which is not documented here.
+
+The return value of a stub hypercall is held by r0/x0, and is 0 on
+success, and HVC_STUB_ERR on error. A stub hypercall is allowed to
+clobber any of the caller-saved registers (x0-x18 on arm64, r0-r3 and
+ip on arm). It is thus recommended to use a function call to perform
+the hypercall.
diff --git a/Documentation/virt/kvm/arm/psci.txt b/Documentation/virt/kvm/arm/psci.txt
new file mode 100644 (file)
index 0000000..559586f
--- /dev/null
@@ -0,0 +1,61 @@
+KVM implements the PSCI (Power State Coordination Interface)
+specification in order to provide services such as CPU on/off, reset
+and power-off to the guest.
+
+The PSCI specification is regularly updated to provide new features,
+and KVM implements these updates if they make sense from a virtualization
+point of view.
+
+This means that a guest booted on two different versions of KVM can
+observe two different "firmware" revisions. This could cause issues if
+a given guest is tied to a particular PSCI revision (unlikely), or if
+a migration causes a different PSCI version to be exposed out of the
+blue to an unsuspecting guest.
+
+In order to remedy this situation, KVM exposes a set of "firmware
+pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
+interface. These registers can be saved/restored by userspace, and set
+to a convenient value if required.
+
+The following register is defined:
+
+* KVM_REG_ARM_PSCI_VERSION:
+
+  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
+    (and thus has already been initialized)
+  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
+    highest PSCI version implemented by KVM and compatible with v0.2)
+  - Allows any PSCI version implemented by KVM and compatible with
+    v0.2 to be set with SET_ONE_REG
+  - Affects the whole VM (even if the register view is per-vcpu)
+
+* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
+  Holds the state of the firmware support to mitigate CVE-2017-5715, as
+  offered by KVM to the guest via a HVC call. The workaround is described
+  under SMCCC_ARCH_WORKAROUND_1 in [1].
+  Accepted values are:
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL: KVM does not offer
+      firmware support for the workaround. The mitigation status for the
+      guest is unknown.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL: The workaround HVC call is
+      available to the guest and required for the mitigation.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED: The workaround HVC call
+      is available to the guest, but it is not needed on this VCPU.
+
+* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
+  Holds the state of the firmware support to mitigate CVE-2018-3639, as
+  offered by KVM to the guest via a HVC call. The workaround is described
+  under SMCCC_ARCH_WORKAROUND_2 in [1].
+  Accepted values are:
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL: A workaround is not
+      available. KVM does not offer firmware support for the workaround.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN: The workaround state is
+      unknown. KVM does not offer firmware support for the workaround.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL: The workaround is available,
+      and can be disabled by a vCPU. If
+      KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED is set, it is active for
+      this vCPU.
+    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED: The workaround is
+      always active on this vCPU or it is not needed.
+
+[1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf
diff --git a/Documentation/virt/kvm/cpuid.rst b/Documentation/virt/kvm/cpuid.rst
new file mode 100644 (file)
index 0000000..01b081f
--- /dev/null
@@ -0,0 +1,107 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============
+KVM CPUID bits
+==============
+
+:Author: Glauber Costa <glommer@gmail.com>
+
+A guest running on a kvm host, can check some of its features using
+cpuid. This is not always guaranteed to work, since userspace can
+mask-out some, or even all KVM-related cpuid features before launching
+a guest.
+
+KVM cpuid functions are:
+
+function: KVM_CPUID_SIGNATURE (0x40000000)
+
+returns::
+
+   eax = 0x40000001
+   ebx = 0x4b4d564b
+   ecx = 0x564b4d56
+   edx = 0x4d
+
+Note that this value in ebx, ecx and edx corresponds to the string "KVMKVMKVM".
+The value in eax corresponds to the maximum cpuid function present in this leaf,
+and will be updated if more functions are added in the future.
+Note also that old hosts set eax value to 0x0. This should
+be interpreted as if the value was 0x40000001.
+This function queries the presence of KVM cpuid leafs.
+
+function: define KVM_CPUID_FEATURES (0x40000001)
+
+returns::
+
+          ebx, ecx
+          eax = an OR'ed group of (1 << flag)
+
+where ``flag`` is defined as below:
+
+================================= =========== ================================
+flag                              value       meaning
+================================= =========== ================================
+KVM_FEATURE_CLOCKSOURCE           0           kvmclock available at msrs
+                                              0x11 and 0x12
+
+KVM_FEATURE_NOP_IO_DELAY          1           not necessary to perform delays
+                                              on PIO operations
+
+KVM_FEATURE_MMU_OP                2           deprecated
+
+KVM_FEATURE_CLOCKSOURCE2          3           kvmclock available at msrs
+
+                                              0x4b564d00 and 0x4b564d01
+KVM_FEATURE_ASYNC_PF              4           async pf can be enabled by
+                                              writing to msr 0x4b564d02
+
+KVM_FEATURE_STEAL_TIME            5           steal time can be enabled by
+                                              writing to msr 0x4b564d03
+
+KVM_FEATURE_PV_EOI                6           paravirtualized end of interrupt
+                                              handler can be enabled by
+                                              writing to msr 0x4b564d04
+
+KVM_FEATURE_PV_UNHAULT            7           guest checks this feature bit
+                                              before enabling paravirtualized
+                                              spinlock support
+
+KVM_FEATURE_PV_TLB_FLUSH          9           guest checks this feature bit
+                                              before enabling paravirtualized
+                                              tlb flush
+
+KVM_FEATURE_ASYNC_PF_VMEXIT       10          paravirtualized async PF VM EXIT
+                                              can be enabled by setting bit 2
+                                              when writing to msr 0x4b564d02
+
+KVM_FEATURE_PV_SEND_IPI           11          guest checks this feature bit
+                                              before enabling paravirtualized
+                                              sebd IPIs
+
+KVM_FEATURE_PV_POLL_CONTROL       12          host-side polling on HLT can
+                                              be disabled by writing
+                                              to msr 0x4b564d05.
+
+KVM_FEATURE_PV_SCHED_YIELD        13          guest checks this feature bit
+                                              before using paravirtualized
+                                              sched yield.
+
+KVM_FEATURE_CLOCSOURCE_STABLE_BIT 24          host will warn if no guest-side
+                                              per-cpu warps are expeced in
+                                              kvmclock
+================================= =========== ================================
+
+::
+
+      edx = an OR'ed group of (1 << flag)
+
+Where ``flag`` here is defined as below:
+
+================== ============ =================================
+flag               value        meaning
+================== ============ =================================
+KVM_HINTS_REALTIME 0            guest checks this feature bit to
+                                determine that vCPUs are never
+                                preempted for an unlimited time
+                                allowing optimizations
+================== ============ =================================
diff --git a/Documentation/virt/kvm/devices/README b/Documentation/virt/kvm/devices/README
new file mode 100644 (file)
index 0000000..34a6983
--- /dev/null
@@ -0,0 +1 @@
+This directory contains specific device bindings for KVM_CAP_DEVICE_CTRL.
diff --git a/Documentation/virt/kvm/devices/arm-vgic-its.txt b/Documentation/virt/kvm/devices/arm-vgic-its.txt
new file mode 100644 (file)
index 0000000..eeaa95b
--- /dev/null
@@ -0,0 +1,181 @@
+ARM Virtual Interrupt Translation Service (ITS)
+===============================================
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_ITS    ARM Interrupt Translation Service Controller
+
+The ITS allows MSI(-X) interrupts to be injected into guests. This extension is
+optional.  Creating a virtual ITS controller also requires a host GICv3 (see
+arm-vgic-v3.txt), but does not depend on having physical ITS controllers.
+
+There can be multiple ITS controllers per guest, each of them has to have
+a separate, non-overlapping MMIO region.
+
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_ITS_ADDR_TYPE (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3 ITS
+      control register frame.
+      This address needs to be 64K aligned and the region covers 128K.
+  Errors:
+    -E2BIG:  Address outside of addressable IPA range
+    -EINVAL: Incorrectly aligned address
+    -EEXIST: Address already configured
+    -EFAULT: Invalid user pointer for attr->addr.
+    -ENODEV: Incorrect attribute or the ITS is not supported.
+
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the ITS, no additional parameter in
+      kvm_device_attr.addr.
+
+    KVM_DEV_ARM_ITS_CTRL_RESET
+      reset the ITS, no additional parameter in kvm_device_attr.addr.
+      See "ITS Reset State" section.
+
+    KVM_DEV_ARM_ITS_SAVE_TABLES
+      save the ITS table data into guest RAM, at the location provisioned
+      by the guest in corresponding registers/table entries.
+
+      The layout of the tables in guest memory defines an ABI. The entries
+      are laid out in little endian format as described in the last paragraph.
+
+    KVM_DEV_ARM_ITS_RESTORE_TABLES
+      restore the ITS tables from guest RAM to ITS internal structures.
+
+      The GICV3 must be restored before the ITS and all ITS registers but
+      the GITS_CTLR must be restored before restoring the ITS tables.
+
+      The GITS_IIDR read-only register must also be restored before
+      calling KVM_DEV_ARM_ITS_RESTORE_TABLES as the IIDR revision field
+      encodes the ABI revision.
+
+      The expected ordering when restoring the GICv3/ITS is described in section
+      "ITS Restore Sequence".
+
+  Errors:
+    -ENXIO:  ITS not properly configured as required prior to setting
+             this attribute
+    -ENOMEM: Memory shortage when allocating ITS internal data
+    -EINVAL: Inconsistent restored data
+    -EFAULT: Invalid guest ram access
+    -EBUSY:  One or more VCPUS are running
+    -EACCES: The virtual ITS is backed by a physical GICv4 ITS, and the
+            state is not available
+
+  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
+  Attributes:
+      The attr field of kvm_device_attr encodes the offset of the
+      ITS register, relative to the ITS control frame base address
+      (ITS_base).
+
+      kvm_device_attr.addr points to a __u64 value whatever the width
+      of the addressed register (32/64 bits). 64 bit registers can only
+      be accessed with full length.
+
+      Writes to read-only registers are ignored by the kernel except for:
+      - GITS_CREADR. It must be restored otherwise commands in the queue
+        will be re-executed after restoring CWRITER. GITS_CREADR must be
+        restored before restoring the GITS_CTLR which is likely to enable the
+        ITS. Also it must be restored after GITS_CBASER since a write to
+        GITS_CBASER resets GITS_CREADR.
+      - GITS_IIDR. The Revision field encodes the table layout ABI revision.
+        In the future we might implement direct injection of virtual LPIs.
+        This will require an upgrade of the table layout and an evolution of
+        the ABI. GITS_IIDR must be restored before calling
+        KVM_DEV_ARM_ITS_RESTORE_TABLES.
+
+      For other registers, getting or setting a register has the same
+      effect as reading/writing the register on real hardware.
+  Errors:
+    -ENXIO: Offset does not correspond to any supported register
+    -EFAULT: Invalid user pointer for attr->addr
+    -EINVAL: Offset is not 64-bit aligned
+    -EBUSY: one or more VCPUS are running
+
+ ITS Restore Sequence:
+ -------------------------
+
+The following ordering must be followed when restoring the GIC and the ITS:
+a) restore all guest memory and create vcpus
+b) restore all redistributors
+c) provide the ITS base address
+   (KVM_DEV_ARM_VGIC_GRP_ADDR)
+d) restore the ITS in the following order:
+   1. Restore GITS_CBASER
+   2. Restore all other GITS_ registers, except GITS_CTLR!
+   3. Load the ITS table data (KVM_DEV_ARM_ITS_RESTORE_TABLES)
+   4. Restore GITS_CTLR
+
+Then vcpus can be started.
+
+ ITS Table ABI REV0:
+ -------------------
+
+ Revision 0 of the ABI only supports the features of a virtual GICv3, and does
+ not support a virtual GICv4 with support for direct injection of virtual
+ interrupts for nested hypervisors.
+
+ The device table and ITT are indexed by the DeviceID and EventID,
+ respectively. The collection table is not indexed by CollectionID, and the
+ entries in the collection are listed in no particular order.
+ All entries are 8 bytes.
+
+ Device Table Entry (DTE):
+
+ bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
+ values:   | V |   next    | ITT_addr |  Size   |
+
+ where;
+ - V indicates whether the entry is valid. If not, other fields
+   are not meaningful.
+ - next: equals to 0 if this entry is the last one; otherwise it
+   corresponds to the DeviceID offset to the next DTE, capped by
+   2^14 -1.
+ - ITT_addr matches bits [51:8] of the ITT address (256 Byte aligned).
+ - Size specifies the supported number of bits for the EventID,
+   minus one
+
+ Collection Table Entry (CTE):
+
+ bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
+ values:   | V |    RES0    |  RDBase   |    ICID     |
+
+ where:
+ - V indicates whether the entry is valid. If not, other fields are
+   not meaningful.
+ - RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
+ - RDBase is the PE number (GICR_TYPER.Processor_Number semantic),
+ - ICID is the collection ID
+
+ Interrupt Translation Entry (ITE):
+
+ bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
+ values:   |    next   |   pINTID  |  ICID    |
+
+ where:
+ - next: equals to 0 if this entry is the last one; otherwise it corresponds
+   to the EventID offset to the next ITE capped by 2^16 -1.
+ - pINTID is the physical LPI ID; if zero, it means the entry is not valid
+   and other fields are not meaningful.
+ - ICID is the collection ID
+
+ ITS Reset State:
+ ----------------
+
+RESET returns the ITS to the same state that it was when first created and
+initialized. When the RESET command returns, the following things are
+guaranteed:
+
+- The ITS is not enabled and quiescent
+  GITS_CTLR.Enabled = 0 .Quiescent=1
+- There is no internally cached state
+- No collection or device table are used
+  GITS_BASER<n>.Valid = 0
+- GITS_CBASER = 0, GITS_CREADR = 0, GITS_CWRITER = 0
+- The ABI version is unchanged and remains the one set when the ITS
+  device was first created.
diff --git a/Documentation/virt/kvm/devices/arm-vgic-v3.txt b/Documentation/virt/kvm/devices/arm-vgic-v3.txt
new file mode 100644 (file)
index 0000000..ff290b4
--- /dev/null
@@ -0,0 +1,251 @@
+ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
+==============================================================
+
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
+
+Only one VGIC instance may be instantiated through this API.  The created VGIC
+will act as the VM interrupt controller, requiring emulated user-space devices
+to inject interrupts to the VGIC instead of directly to CPUs.  It is not
+possible to create both a GICv3 and GICv2 on the same VM.
+
+Creating a guest GICv3 device requires a host GICv3 as well.
+
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3 distributor
+      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned and the region covers 64 KByte.
+
+    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
+      Base address in the guest physical address space of the GICv3
+      redistributor register mappings. There are two 64K pages for each
+      VCPU and all of the redistributor pages are contiguous.
+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+      This address needs to be 64K aligned.
+
+    KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION (rw, 64-bit)
+      The attribute data pointed to by kvm_device_attr.addr is a __u64 value:
+      bits:     | 63   ....  52  |  51   ....   16 | 15 - 12  |11 - 0
+      values:   |     count      |       base      |  flags   | index
+      - index encodes the unique redistributor region index
+      - flags: reserved for future use, currently 0
+      - base field encodes bits [51:16] of the guest physical base address
+        of the first redistributor in the region.
+      - count encodes the number of redistributors in the region. Must be
+        greater than 0.
+      There are two 64K pages for each redistributor in the region and
+      redistributors are laid out contiguously within the region. Regions
+      are filled with redistributors in the index order. The sum of all
+      region count fields must be greater than or equal to the number of
+      VCPUs. Redistributor regions must be registered in the incremental
+      index order, starting from index 0.
+      The characteristics of a specific redistributor region can be read
+      by presetting the index field in the attr data.
+      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+
+  It is invalid to mix calls with KVM_VGIC_V3_ADDR_TYPE_REDIST and
+  KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attributes.
+
+  Errors:
+    -E2BIG:  Address outside of addressable IPA range
+    -EINVAL: Incorrectly aligned address, bad redistributor region
+             count/index, mixed redistributor region attribute usage
+    -EEXIST: Address already configured
+    -ENOENT: Attempt to read the characteristics of a non existing
+             redistributor region
+    -ENXIO:  The group or attribute is unknown/unsupported for this device
+             or hardware support is missing.
+    -EFAULT: Invalid user pointer for attr->addr.
+
+
+  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
+  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  32  |  31   ....    0 |
+    values:   |      mpidr     |      offset     |
+
+    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
+    __u32 value.  64-bit registers must be accessed by separately accessing the
+    lower and higher word.
+
+    Writes to read-only registers are ignored by the kernel.
+
+    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
+    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
+    specified by the mpidr.
+
+    The offset is relative to the "[Re]Distributor base address" as defined
+    in the GICv3/4 specs.  Getting or setting such a register has the same
+    effect as reading or writing the register on real hardware, except for the
+    following registers: GICD_STATUSR, GICR_STATUSR, GICD_ISPENDR,
+    GICR_ISPENDR0, GICD_ICPENDR, and GICR_ICPENDR0.  These registers behave
+    differently when accessed via this interface compared to their
+    architecturally defined behavior to allow software a full view of the
+    VGIC's internal state.
+
+    The mpidr field is used to specify which
+    redistributor is accessed.  The mpidr is ignored for the distributor.
+
+    The mpidr encoding is based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+
+    Note that distributor fields are not banked, but return the same value
+    regardless of the mpidr used to access the register.
+
+    GICD_IIDR.Revision is updated when the KVM implementation is changed in a
+    way directly observable by the guest or userspace.  Userspace should read
+    GICD_IIDR from KVM and write back the read value to confirm its expected
+    behavior is aligned with the KVM implementation.  Userspace should set
+    GICD_IIDR before setting any other registers to ensure the expected
+    behavior.
+
+
+    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
+    that a write of a clear bit has no effect, whereas a write with a set bit
+    clears that value.  To allow userspace to freely set the values of these two
+    registers, setting the attributes with the register offsets for these two
+    registers simply sets the non-reserved bits to the value written.
+
+
+    Accesses (reads and writes) to the GICD_ISPENDR register region and
+    GICR_ISPENDR0 registers get/set the value of the latched pending state for
+    the interrupts.
+
+    This is identical to the value returned by a guest read from ISPENDR for an
+    edge triggered interrupt, but may differ for level triggered interrupts.
+    For edge triggered interrupts, once an interrupt becomes pending (whether
+    because of an edge detected on the input line or because of a guest write
+    to ISPENDR) this state is "latched", and only cleared when either the
+    interrupt is activated or when the guest writes to ICPENDR. A level
+    triggered interrupt may be pending either because the level input is held
+    high by a device, or because of a guest write to the ISPENDR register. Only
+    ISPENDR writes are latched; if the device lowers the line level then the
+    interrupt is no longer pending unless the guest also wrote to ISPENDR, and
+    conversely writes to ICPENDR or activations of the interrupt do not clear
+    the pending status if the line level is still being held high.  (These
+    rules are documented in the GICv3 specification descriptions of the ICPENDR
+    and ISPENDR registers.) For a level triggered interrupt the value accessed
+    here is that of the latch which is set by ISPENDR and cleared by ICPENDR or
+    interrupt activation, whereas the value returned by a guest read from
+    ISPENDR is the logical OR of the latch value and the input line level.
+
+    Raw access to the latch state is provided to userspace so that it can save
+    and restore the entire GIC internal state (which is defined by the
+    combination of the current input line level and the latch state, and cannot
+    be deduced from purely the line level and the value of the ISPENDR
+    registers).
+
+    Accesses to GICD_ICPENDR register region and GICR_ICPENDR0 registers have
+    RAZ/WI semantics, meaning that reads always return 0 and writes are always
+    ignored.
+
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+
+
+  KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
+    values:   |         mpidr         |      RES     |    instr    |
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+
+    The instr field encodes the system register to access based on the fields
+    defined in the A64 instruction set encoding for system register access
+    (RES means the bits are reserved for future use and should be zero):
+
+      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
+      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
+
+    All system regs accessed through this API are (rw, 64-bit) and
+    kvm_device_attr.addr points to a __u64 value.
+
+    KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS accesses the CPU interface registers for the
+    CPU specified by the mpidr field.
+
+    CPU interface registers access is not implemented for AArch32 mode.
+    Error -ENXIO is returned when accessed in AArch32 mode.
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: VCPU is running
+    -EINVAL: Invalid mpidr or register value supplied
+
+
+  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
+  Attributes:
+    A value describing the number of interrupts (SGI, PPI and SPI) for
+    this GIC instance, ranging from 64 to 1024, in increments of 32.
+
+    kvm_device_attr.addr points to a __u32 value.
+
+  Errors:
+    -EINVAL: Value set is out of the expected range
+    -EBUSY: Value has already be set.
+
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the VGIC, no additional parameter in
+      kvm_device_attr.addr.
+    KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES
+      save all LPI pending bits into guest RAM pending tables.
+
+      The first kB of the pending table is not altered by this operation.
+  Errors:
+    -ENXIO: VGIC not properly configured as required prior to calling
+     this attribute
+    -ENODEV: no online VCPU
+    -ENOMEM: memory shortage when allocating vgic internal data
+    -EFAULT: Invalid guest ram access
+    -EBUSY:  One or more VCPUS are running
+
+
+  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
+  Attributes:
+    The attr field of kvm_device_attr encodes the following values:
+    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
+    values:   |         mpidr         |      info       |   vINTID   |
+
+    The vINTID specifies which set of IRQs is reported on.
+
+    The info field specifies which information userspace wants to get or set
+    using this interface.  Currently we support the following info values:
+
+      VGIC_LEVEL_INFO_LINE_LEVEL:
+       Get/Set the input level of the IRQ line for a set of 32 contiguously
+       numbered interrupts.
+       vINTID must be a multiple of 32.
+
+       kvm_device_attr.addr points to a __u32 value which will contain a
+       bitmap where a set bit means the interrupt level is asserted.
+
+       Bit[n] indicates the status for interrupt vINTID + n.
+
+    SGIs and any interrupt with a higher ID than the number of interrupts
+    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
+    therefore not supported by this interface.
+
+    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
+    reported with the same value regardless of the mpidr specified.
+
+    The mpidr field encodes the CPU ID based on the affinity information in the
+    architecture defined MPIDR, and the field is encoded as follows:
+      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
+      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
+  Errors:
+    -EINVAL: vINTID is not multiple of 32 or
+     info field is not VGIC_LEVEL_INFO_LINE_LEVEL
diff --git a/Documentation/virt/kvm/devices/arm-vgic.txt b/Documentation/virt/kvm/devices/arm-vgic.txt
new file mode 100644 (file)
index 0000000..97b6518
--- /dev/null
@@ -0,0 +1,127 @@
+ARM Virtual Generic Interrupt Controller v2 (VGIC)
+==================================================
+
+Device types supported:
+  KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
+
+Only one VGIC instance may be instantiated through either this API or the
+legacy KVM_CREATE_IRQCHIP API.  The created VGIC will act as the VM interrupt
+controller, requiring emulated user-space devices to inject interrupts to the
+VGIC instead of directly to CPUs.
+
+GICv3 implementations with hardware compatibility support allow creating a
+guest GICv2 through this interface.  For information on creating a guest GICv3
+device and guest ITS devices, see arm-vgic-v3.txt.  It is not possible to
+create both a GICv3 and GICv2 device on the same VM.
+
+
+Groups:
+  KVM_DEV_ARM_VGIC_GRP_ADDR
+  Attributes:
+    KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
+      Base address in the guest physical address space of the GIC distributor
+      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
+      This address needs to be 4K aligned and the region covers 4 KByte.
+
+    KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
+      Base address in the guest physical address space of the GIC virtual cpu
+      interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
+      This address needs to be 4K aligned and the region covers 4 KByte.
+  Errors:
+    -E2BIG:  Address outside of addressable IPA range
+    -EINVAL: Incorrectly aligned address
+    -EEXIST: Address already configured
+    -ENXIO:  The group or attribute is unknown/unsupported for this device
+             or hardware support is missing.
+    -EFAULT: Invalid user pointer for attr->addr.
+
+  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
+    values:   |    reserved   | vcpu_index |      offset     |
+
+    All distributor regs are (rw, 32-bit)
+
+    The offset is relative to the "Distributor base address" as defined in the
+    GICv2 specs.  Getting or setting such a register has the same effect as
+    reading or writing the register on the actual hardware from the cpu whose
+    index is specified with the vcpu_index field.  Note that most distributor
+    fields are not banked, but return the same value regardless of the
+    vcpu_index used to access the register.
+
+    GICD_IIDR.Revision is updated when the KVM implementation of an emulated
+    GICv2 is changed in a way directly observable by the guest or userspace.
+    Userspace should read GICD_IIDR from KVM and write back the read value to
+    confirm its expected behavior is aligned with the KVM implementation.
+    Userspace should set GICD_IIDR before setting any other registers (both
+    KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_CPU_REGS) to ensure
+    the expected behavior. Unless GICD_IIDR has been set from userspace, writes
+    to the interrupt group registers (GICD_IGROUPR) are ignored.
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+    -EINVAL: Invalid vcpu_index supplied
+
+  KVM_DEV_ARM_VGIC_GRP_CPU_REGS
+  Attributes:
+    The attr field of kvm_device_attr encodes two values:
+    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
+    values:   |    reserved   | vcpu_index |      offset     |
+
+    All CPU interface regs are (rw, 32-bit)
+
+    The offset specifies the offset from the "CPU interface base address" as
+    defined in the GICv2 specs.  Getting or setting such a register has the
+    same effect as reading or writing the register on the actual hardware.
+
+    The Active Priorities Registers APRn are implementation defined, so we set a
+    fixed format for our implementation that fits with the model of a "GICv2
+    implementation without the security extensions" which we present to the
+    guest.  This interface always exposes four register APR[0-3] describing the
+    maximum possible 128 preemption levels.  The semantics of the register
+    indicate if any interrupts in a given preemption level are in the active
+    state by setting the corresponding bit.
+
+    Thus, preemption level X has one or more active interrupts if and only if:
+
+      APRn[X mod 32] == 0b1,  where n = X / 32
+
+    Bits for undefined preemption levels are RAZ/WI.
+
+    Note that this differs from a CPU's view of the APRs on hardware in which
+    a GIC without the security extensions expose group 0 and group 1 active
+    priorities in separate register groups, whereas we show a combined view
+    similar to GICv2's GICH_APR.
+
+    For historical reasons and to provide ABI compatibility with userspace we
+    export the GICC_PMR register in the format of the GICH_VMCR.VMPriMask
+    field in the lower 5 bits of a word, meaning that userspace must always
+    use the lower 5 bits to communicate with the KVM device and must shift the
+    value left by 3 places to obtain the actual priority mask level.
+
+  Errors:
+    -ENXIO: Getting or setting this register is not yet supported
+    -EBUSY: One or more VCPUs are running
+    -EINVAL: Invalid vcpu_index supplied
+
+  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
+  Attributes:
+    A value describing the number of interrupts (SGI, PPI and SPI) for
+    this GIC instance, ranging from 64 to 1024, in increments of 32.
+
+  Errors:
+    -EINVAL: Value set is out of the expected range
+    -EBUSY: Value has already be set, or GIC has already been initialized
+            with default values.
+
+  KVM_DEV_ARM_VGIC_GRP_CTRL
+  Attributes:
+    KVM_DEV_ARM_VGIC_CTRL_INIT
+      request the initialization of the VGIC or ITS, no additional parameter
+      in kvm_device_attr.addr.
+  Errors:
+    -ENXIO: VGIC not properly configured as required prior to calling
+     this attribute
+    -ENODEV: no online VCPU
+    -ENOMEM: memory shortage when allocating vgic internal data
diff --git a/Documentation/virt/kvm/devices/mpic.txt b/Documentation/virt/kvm/devices/mpic.txt
new file mode 100644 (file)
index 0000000..8257397
--- /dev/null
@@ -0,0 +1,53 @@
+MPIC interrupt controller
+=========================
+
+Device types supported:
+  KVM_DEV_TYPE_FSL_MPIC_20     Freescale MPIC v2.0
+  KVM_DEV_TYPE_FSL_MPIC_42     Freescale MPIC v4.2
+
+Only one MPIC instance, of any type, may be instantiated.  The created
+MPIC will act as the system interrupt controller, connecting to each
+vcpu's interrupt inputs.
+
+Groups:
+  KVM_DEV_MPIC_GRP_MISC
+  Attributes:
+    KVM_DEV_MPIC_BASE_ADDR (rw, 64-bit)
+      Base address of the 256 KiB MPIC register space.  Must be
+      naturally aligned.  A value of zero disables the mapping.
+      Reset value is zero.
+
+  KVM_DEV_MPIC_GRP_REGISTER (rw, 32-bit)
+    Access an MPIC register, as if the access were made from the guest.
+    "attr" is the byte offset into the MPIC register space.  Accesses
+    must be 4-byte aligned.
+
+    MSIs may be signaled by using this attribute group to write
+    to the relevant MSIIR.
+
+  KVM_DEV_MPIC_GRP_IRQ_ACTIVE (rw, 32-bit)
+    IRQ input line for each standard openpic source.  0 is inactive and 1
+    is active, regardless of interrupt sense.
+
+    For edge-triggered interrupts:  Writing 1 is considered an activating
+    edge, and writing 0 is ignored.  Reading returns 1 if a previously
+    signaled edge has not been acknowledged, and 0 otherwise.
+
+    "attr" is the IRQ number.  IRQ numbers for standard sources are the
+    byte offset of the relevant IVPR from EIVPR0, divided by 32.
+
+IRQ Routing:
+
+  The MPIC emulation supports IRQ routing. Only a single MPIC device can
+  be instantiated. Once that device has been created, it's available as
+  irqchip id 0.
+
+  This irqchip 0 has 256 interrupt pins, which expose the interrupts in
+  the main array of interrupt sources (a.k.a. "SRC" interrupts).
+
+  The numbering is the same as the MPIC device tree binding -- based on
+  the register offset from the beginning of the sources array, without
+  regard to any subdivisions in chip documentation such as "internal"
+  or "external" interrupts.
+
+  Access to non-SRC interrupts is not implemented through IRQ routing mechanisms.
diff --git a/Documentation/virt/kvm/devices/s390_flic.txt b/Documentation/virt/kvm/devices/s390_flic.txt
new file mode 100644 (file)
index 0000000..a4e20a0
--- /dev/null
@@ -0,0 +1,163 @@
+FLIC (floating interrupt controller)
+====================================
+
+FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some
+machine check interruptions. All interrupts are stored in a per-vm list of
+pending interrupts. FLIC performs operations on this list.
+
+Only one FLIC instance may be instantiated.
+
+FLIC provides support to
+- add interrupts (KVM_DEV_FLIC_ENQUEUE)
+- inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS)
+- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS)
+- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
+- enable/disable for the guest transparent async page faults
+- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
+- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
+- inject adapter interrupts on a specified adapter (KVM_DEV_FLIC_AIRQ_INJECT)
+- get/set all AIS mode states (KVM_DEV_FLIC_AISM_ALL)
+
+Groups:
+  KVM_DEV_FLIC_ENQUEUE
+    Passes a buffer and length into the kernel which are then injected into
+    the list of pending interrupts.
+    attr->addr contains the pointer to the buffer and attr->attr contains
+    the length of the buffer.
+    The format of the data structure kvm_s390_irq as it is copied from userspace
+    is defined in usr/include/linux/kvm.h.
+
+  KVM_DEV_FLIC_GET_ALL_IRQS
+    Copies all floating interrupts into a buffer provided by userspace.
+    When the buffer is too small it returns -ENOMEM, which is the indication
+    for userspace to try again with a bigger buffer.
+    -ENOBUFS is returned when the allocation of a kernelspace buffer has
+    failed.
+    -EFAULT is returned when copying data to userspace failed.
+    All interrupts remain pending, i.e. are not deleted from the list of
+    currently pending interrupts.
+    attr->addr contains the userspace address of the buffer into which all
+    interrupt data will be copied.
+    attr->attr contains the size of the buffer in bytes.
+
+  KVM_DEV_FLIC_CLEAR_IRQS
+    Simply deletes all elements from the list of currently pending floating
+    interrupts.  No interrupts are injected into the guest.
+
+  KVM_DEV_FLIC_CLEAR_IO_IRQ
+    Deletes one (if any) I/O interrupt for a subchannel identified by the
+    subsystem identification word passed via the buffer specified by
+    attr->addr (address) and attr->attr (length).
+
+  KVM_DEV_FLIC_APF_ENABLE
+    Enables async page faults for the guest. So in case of a major page fault
+    the host is allowed to handle this async and continues the guest.
+
+  KVM_DEV_FLIC_APF_DISABLE_WAIT
+    Disables async page faults for the guest and waits until already pending
+    async page faults are done. This is necessary to trigger a completion interrupt
+    for every init interrupt before migrating the interrupt list.
+
+  KVM_DEV_FLIC_ADAPTER_REGISTER
+    Register an I/O adapter interrupt source. Takes a kvm_s390_io_adapter
+    describing the adapter to register:
+
+struct kvm_s390_io_adapter {
+       __u32 id;
+       __u8 isc;
+       __u8 maskable;
+       __u8 swap;
+       __u8 flags;
+};
+
+   id contains the unique id for the adapter, isc the I/O interruption subclass
+   to use, maskable whether this adapter may be masked (interrupts turned off),
+   swap whether the indicators need to be byte swapped, and flags contains
+   further characteristics of the adapter.
+   Currently defined values for 'flags' are:
+   - KVM_S390_ADAPTER_SUPPRESSIBLE: adapter is subject to AIS
+     (adapter-interrupt-suppression) facility. This flag only has an effect if
+     the AIS capability is enabled.
+   Unknown flag values are ignored.
+
+
+  KVM_DEV_FLIC_ADAPTER_MODIFY
+    Modifies attributes of an existing I/O adapter interrupt source. Takes
+    a kvm_s390_io_adapter_req specifying the adapter and the operation:
+
+struct kvm_s390_io_adapter_req {
+       __u32 id;
+       __u8 type;
+       __u8 mask;
+       __u16 pad0;
+       __u64 addr;
+};
+
+    id specifies the adapter and type the operation. The supported operations
+    are:
+
+    KVM_S390_IO_ADAPTER_MASK
+      mask or unmask the adapter, as specified in mask
+
+    KVM_S390_IO_ADAPTER_MAP
+      perform a gmap translation for the guest address provided in addr,
+      pin a userspace page for the translated address and add it to the
+      list of mappings
+      Note: A new mapping will be created unconditionally; therefore,
+            the calling code should avoid making duplicate mappings.
+
+    KVM_S390_IO_ADAPTER_UNMAP
+      release a userspace page for the translated address specified in addr
+      from the list of mappings
+
+  KVM_DEV_FLIC_AISM
+    modify the adapter-interruption-suppression mode for a given isc if the
+    AIS capability is enabled. Takes a kvm_s390_ais_req describing:
+
+struct kvm_s390_ais_req {
+       __u8 isc;
+       __u16 mode;
+};
+
+    isc contains the target I/O interruption subclass, mode the target
+    adapter-interruption-suppression mode. The following modes are
+    currently supported:
+    - KVM_S390_AIS_MODE_ALL: ALL-Interruptions Mode, i.e. airq injection
+      is always allowed;
+    - KVM_S390_AIS_MODE_SINGLE: SINGLE-Interruption Mode, i.e. airq
+      injection is only allowed once and the following adapter interrupts
+      will be suppressed until the mode is set again to ALL-Interruptions
+      or SINGLE-Interruption mode.
+
+  KVM_DEV_FLIC_AIRQ_INJECT
+    Inject adapter interrupts on a specified adapter.
+    attr->attr contains the unique id for the adapter, which allows for
+    adapter-specific checks and actions.
+    For adapters subject to AIS, handle the airq injection suppression for
+    an isc according to the adapter-interruption-suppression mode on condition
+    that the AIS capability is enabled.
+
+  KVM_DEV_FLIC_AISM_ALL
+    Gets or sets the adapter-interruption-suppression mode for all ISCs. Takes
+    a kvm_s390_ais_all describing:
+
+struct kvm_s390_ais_all {
+       __u8 simm; /* Single-Interruption-Mode mask */
+       __u8 nimm; /* No-Interruption-Mode mask *
+};
+
+    simm contains Single-Interruption-Mode mask for all ISCs, nimm contains
+    No-Interruption-Mode mask for all ISCs. Each bit in simm and nimm corresponds
+    to an ISC (MSB0 bit 0 to ISC 0 and so on). The combination of simm bit and
+    nimm bit presents AIS mode for a ISC.
+
+    KVM_DEV_FLIC_AISM_ALL is indicated by KVM_CAP_S390_AIS_MIGRATION.
+
+Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
+FLIC with an unknown group or attribute gives the error code EINVAL (instead of
+ENXIO, as specified in the API documentation). It is not possible to conclude
+that a FLIC operation is unavailable based on the error code resulting from a
+usage attempt.
+
+Note: The KVM_DEV_FLIC_CLEAR_IO_IRQ ioctl will return EINVAL in case a zero
+schid is specified.
diff --git a/Documentation/virt/kvm/devices/vcpu.txt b/Documentation/virt/kvm/devices/vcpu.txt
new file mode 100644 (file)
index 0000000..2b5dab1
--- /dev/null
@@ -0,0 +1,62 @@
+Generic vcpu interface
+====================================
+
+The virtual cpu "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
+KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same struct
+kvm_device_attr as other devices, but targets VCPU-wide settings and controls.
+
+The groups and attributes per virtual cpu, if any, are architecture specific.
+
+1. GROUP: KVM_ARM_VCPU_PMU_V3_CTRL
+Architectures: ARM64
+
+1.1. ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_IRQ
+Parameters: in kvm_device_attr.addr the address for PMU overflow interrupt is a
+            pointer to an int
+Returns: -EBUSY: The PMU overflow interrupt is already set
+         -ENXIO: The overflow interrupt not set when attempting to get it
+         -ENODEV: PMUv3 not supported
+         -EINVAL: Invalid PMU overflow interrupt number supplied or
+                  trying to set the IRQ number without using an in-kernel
+                  irqchip.
+
+A value describing the PMUv3 (Performance Monitor Unit v3) overflow interrupt
+number for this vcpu. This interrupt could be a PPI or SPI, but the interrupt
+type must be same for each vcpu. As a PPI, the interrupt number is the same for
+all vcpus, while as an SPI it must be a separate number per vcpu.
+
+1.2 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_INIT
+Parameters: no additional parameter in kvm_device_attr.addr
+Returns: -ENODEV: PMUv3 not supported or GIC not initialized
+         -ENXIO: PMUv3 not properly configured or in-kernel irqchip not
+                 configured as required prior to calling this attribute
+         -EBUSY: PMUv3 already initialized
+
+Request the initialization of the PMUv3.  If using the PMUv3 with an in-kernel
+virtual GIC implementation, this must be done after initializing the in-kernel
+irqchip.
+
+
+2. GROUP: KVM_ARM_VCPU_TIMER_CTRL
+Architectures: ARM,ARM64
+
+2.1. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_VTIMER
+2.2. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_PTIMER
+Parameters: in kvm_device_attr.addr the address for the timer interrupt is a
+            pointer to an int
+Returns: -EINVAL: Invalid timer interrupt number
+         -EBUSY:  One or more VCPUs has already run
+
+A value describing the architected timer interrupt number when connected to an
+in-kernel virtual GIC.  These must be a PPI (16 <= intid < 32).  Setting the
+attribute overrides the default values (see below).
+
+KVM_ARM_VCPU_TIMER_IRQ_VTIMER: The EL1 virtual timer intid (default: 27)
+KVM_ARM_VCPU_TIMER_IRQ_PTIMER: The EL1 physical timer intid (default: 30)
+
+Setting the same PPI for different timers will prevent the VCPUs from running.
+Setting the interrupt number on a VCPU configures all VCPUs created at that
+time to use the number provided for a given timer, overwriting any previously
+configured values on other VCPUs.  Userspace should configure the interrupt
+numbers on at least one VCPU after creating all VCPUs and before running any
+VCPUs.
diff --git a/Documentation/virt/kvm/devices/vfio.txt b/Documentation/virt/kvm/devices/vfio.txt
new file mode 100644 (file)
index 0000000..528c77c
--- /dev/null
@@ -0,0 +1,36 @@
+VFIO virtual device
+===================
+
+Device types supported:
+  KVM_DEV_TYPE_VFIO
+
+Only one VFIO instance may be created per VM.  The created device
+tracks VFIO groups in use by the VM and features of those groups
+important to the correctness and acceleration of the VM.  As groups
+are enabled and disabled for use by the VM, KVM should be updated
+about their presence.  When registered with KVM, a reference to the
+VFIO-group is held by KVM.
+
+Groups:
+  KVM_DEV_VFIO_GROUP
+
+KVM_DEV_VFIO_GROUP attributes:
+  KVM_DEV_VFIO_GROUP_ADD: Add a VFIO group to VFIO-KVM device tracking
+       kvm_device_attr.addr points to an int32_t file descriptor
+       for the VFIO group.
+  KVM_DEV_VFIO_GROUP_DEL: Remove a VFIO group from VFIO-KVM device tracking
+       kvm_device_attr.addr points to an int32_t file descriptor
+       for the VFIO group.
+  KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE: attaches a guest visible TCE table
+       allocated by sPAPR KVM.
+       kvm_device_attr.addr points to a struct:
+
+       struct kvm_vfio_spapr_tce {
+               __s32   groupfd;
+               __s32   tablefd;
+       };
+
+       where
+       @groupfd is a file descriptor for a VFIO group;
+       @tablefd is a file descriptor for a TCE table allocated via
+               KVM_CREATE_SPAPR_TCE.
diff --git a/Documentation/virt/kvm/devices/vm.txt b/Documentation/virt/kvm/devices/vm.txt
new file mode 100644 (file)
index 0000000..4ffb82b
--- /dev/null
@@ -0,0 +1,270 @@
+Generic vm interface
+====================================
+
+The virtual machine "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
+KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same
+struct kvm_device_attr as other devices, but targets VM-wide settings
+and controls.
+
+The groups and attributes per virtual machine, if any, are architecture
+specific.
+
+1. GROUP: KVM_S390_VM_MEM_CTRL
+Architectures: s390
+
+1.1. ATTRIBUTE: KVM_S390_VM_MEM_ENABLE_CMMA
+Parameters: none
+Returns: -EBUSY if a vcpu is already defined, otherwise 0
+
+Enables Collaborative Memory Management Assist (CMMA) for the virtual machine.
+
+1.2. ATTRIBUTE: KVM_S390_VM_MEM_CLR_CMMA
+Parameters: none
+Returns: -EINVAL if CMMA was not enabled
+         0 otherwise
+
+Clear the CMMA status for all guest pages, so any pages the guest marked
+as unused are again used any may not be reclaimed by the host.
+
+1.3. ATTRIBUTE KVM_S390_VM_MEM_LIMIT_SIZE
+Parameters: in attr->addr the address for the new limit of guest memory
+Returns: -EFAULT if the given address is not accessible
+         -EINVAL if the virtual machine is of type UCONTROL
+         -E2BIG if the given guest memory is to big for that machine
+         -EBUSY if a vcpu is already defined
+         -ENOMEM if not enough memory is available for a new shadow guest mapping
+          0 otherwise
+
+Allows userspace to query the actual limit and set a new limit for
+the maximum guest memory size. The limit will be rounded up to
+2048 MB, 4096 GB, 8192 TB respectively, as this limit is governed by
+the number of page table levels. In the case that there is no limit we will set
+the limit to KVM_S390_NO_MEM_LIMIT (U64_MAX).
+
+2. GROUP: KVM_S390_VM_CPU_MODEL
+Architectures: s390
+
+2.1. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE (r/o)
+
+Allows user space to retrieve machine and kvm specific cpu related information:
+
+struct kvm_s390_vm_cpu_machine {
+       __u64 cpuid;           # CPUID of host
+       __u32 ibc;             # IBC level range offered by host
+       __u8  pad[4];
+       __u64 fac_mask[256];   # set of cpu facilities enabled by KVM
+       __u64 fac_list[256];   # set of cpu facilities offered by host
+}
+
+Parameters: address of buffer to store the machine related cpu data
+            of type struct kvm_s390_vm_cpu_machine*
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           -ENOMEM if not enough memory is available to process the ioctl
+           0 in case of success
+
+2.2. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR (r/w)
+
+Allows user space to retrieve or request to change cpu related information for a vcpu:
+
+struct kvm_s390_vm_cpu_processor {
+       __u64 cpuid;           # CPUID currently (to be) used by this vcpu
+       __u16 ibc;             # IBC level currently (to be) used by this vcpu
+       __u8  pad[6];
+       __u64 fac_list[256];   # set of cpu facilities currently (to be) used
+                              # by this vcpu
+}
+
+KVM does not enforce or limit the cpu model data in any form. Take the information
+retrieved by means of KVM_S390_VM_CPU_MACHINE as hint for reasonable configuration
+setups. Instruction interceptions triggered by additionally set facility bits that
+are not handled by KVM need to by imlemented in the VM driver code.
+
+Parameters: address of buffer to store/set the processor related cpu
+           data of type struct kvm_s390_vm_cpu_processor*.
+Returns:    -EBUSY in case 1 or more vcpus are already activated (only in write case)
+           -EFAULT if the given address is not accessible from kernel space
+           -ENOMEM if not enough memory is available to process the ioctl
+           0 in case of success
+
+2.3. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_FEAT (r/o)
+
+Allows user space to retrieve available cpu features. A feature is available if
+provided by the hardware and supported by kvm. In theory, cpu features could
+even be completely emulated by kvm.
+
+struct kvm_s390_vm_cpu_feat {
+        __u64 feat[16]; # Bitmap (1 = feature available), MSB 0 bit numbering
+};
+
+Parameters: address of a buffer to load the feature list from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           0 in case of success.
+
+2.4. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_FEAT (r/w)
+
+Allows user space to retrieve or change enabled cpu features for all VCPUs of a
+VM. Features that are not available cannot be enabled.
+
+See 2.3. for a description of the parameter struct.
+
+Parameters: address of a buffer to store/load the feature list from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           -EINVAL if a cpu feature that is not available is to be enabled.
+           -EBUSY if at least one VCPU has already been defined.
+           0 in case of success.
+
+2.5. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_SUBFUNC (r/o)
+
+Allows user space to retrieve available cpu subfunctions without any filtering
+done by a set IBC. These subfunctions are indicated to the guest VCPU via
+query or "test bit" subfunctions and used e.g. by cpacf functions, plo and ptff.
+
+A subfunction block is only valid if KVM_S390_VM_CPU_MACHINE contains the
+STFL(E) bit introducing the affected instruction. If the affected instruction
+indicates subfunctions via a "query subfunction", the response block is
+contained in the returned struct. If the affected instruction
+indicates subfunctions via a "test bit" mechanism, the subfunction codes are
+contained in the returned struct in MSB 0 bit numbering.
+
+struct kvm_s390_vm_cpu_subfunc {
+       u8 plo[32];           # always valid (ESA/390 feature)
+       u8 ptff[16];          # valid with TOD-clock steering
+       u8 kmac[16];          # valid with Message-Security-Assist
+       u8 kmc[16];           # valid with Message-Security-Assist
+       u8 km[16];            # valid with Message-Security-Assist
+       u8 kimd[16];          # valid with Message-Security-Assist
+       u8 klmd[16];          # valid with Message-Security-Assist
+       u8 pckmo[16];         # valid with Message-Security-Assist-Extension 3
+       u8 kmctr[16];         # valid with Message-Security-Assist-Extension 4
+       u8 kmf[16];           # valid with Message-Security-Assist-Extension 4
+       u8 kmo[16];           # valid with Message-Security-Assist-Extension 4
+       u8 pcc[16];           # valid with Message-Security-Assist-Extension 4
+       u8 ppno[16];          # valid with Message-Security-Assist-Extension 5
+       u8 kma[16];           # valid with Message-Security-Assist-Extension 8
+       u8 kdsa[16];          # valid with Message-Security-Assist-Extension 9
+       u8 reserved[1792];    # reserved for future instructions
+};
+
+Parameters: address of a buffer to load the subfunction blocks from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           0 in case of success.
+
+2.6. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_SUBFUNC (r/w)
+
+Allows user space to retrieve or change cpu subfunctions to be indicated for
+all VCPUs of a VM. This attribute will only be available if kernel and
+hardware support are in place.
+
+The kernel uses the configured subfunction blocks for indication to
+the guest. A subfunction block will only be used if the associated STFL(E) bit
+has not been disabled by user space (so the instruction to be queried is
+actually available for the guest).
+
+As long as no data has been written, a read will fail. The IBC will be used
+to determine available subfunctions in this case, this will guarantee backward
+compatibility.
+
+See 2.5. for a description of the parameter struct.
+
+Parameters: address of a buffer to store/load the subfunction blocks from.
+Returns:    -EFAULT if the given address is not accessible from kernel space.
+           -EINVAL when reading, if there was no write yet.
+           -EBUSY if at least one VCPU has already been defined.
+           0 in case of success.
+
+3. GROUP: KVM_S390_VM_TOD
+Architectures: s390
+
+3.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH
+
+Allows user space to set/get the TOD clock extension (u8) (superseded by
+KVM_S390_VM_TOD_EXT).
+
+Parameters: address of a buffer in user space to store the data (u8) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           -EINVAL if setting the TOD clock extension to != 0 is not supported
+
+3.2. ATTRIBUTE: KVM_S390_VM_TOD_LOW
+
+Allows user space to set/get bits 0-63 of the TOD clock register as defined in
+the POP (u64).
+
+Parameters: address of a buffer in user space to store the data (u64) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+
+3.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
+Allows user space to set/get bits 0-63 of the TOD clock register as defined in
+the POP (u64). If the guest CPU model supports the TOD clock extension (u8), it
+also allows user space to get/set it. If the guest CPU model does not support
+it, it is stored as 0 and not allowed to be set to a value != 0.
+
+Parameters: address of a buffer in user space to store the data
+            (kvm_s390_vm_tod_clock) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           -EINVAL if setting the TOD clock extension to != 0 is not supported
+
+4. GROUP: KVM_S390_VM_CRYPTO
+Architectures: s390
+
+4.1. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_AES_KW (w/o)
+
+Allows user space to enable aes key wrapping, including generating a new
+wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.2. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_DEA_KW (w/o)
+
+Allows user space to enable dea key wrapping, including generating a new
+wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.3. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_AES_KW (w/o)
+
+Allows user space to disable aes key wrapping, clearing the wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.4. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_DEA_KW (w/o)
+
+Allows user space to disable dea key wrapping, clearing the wrapping key.
+
+Parameters: none
+Returns:    0
+
+5. GROUP: KVM_S390_VM_MIGRATION
+Architectures: s390
+
+5.1. ATTRIBUTE: KVM_S390_VM_MIGRATION_STOP (w/o)
+
+Allows userspace to stop migration mode, needed for PGSTE migration.
+Setting this attribute when migration mode is not active will have no
+effects.
+
+Parameters: none
+Returns:    0
+
+5.2. ATTRIBUTE: KVM_S390_VM_MIGRATION_START (w/o)
+
+Allows userspace to start migration mode, needed for PGSTE migration.
+Setting this attribute when migration mode is already active will have
+no effects.
+
+Parameters: none
+Returns:    -ENOMEM if there is not enough free memory to start migration mode
+           -EINVAL if the state of the VM is invalid (e.g. no memory defined)
+           0 in case of success.
+
+5.3. ATTRIBUTE: KVM_S390_VM_MIGRATION_STATUS (r/o)
+
+Allows userspace to query the status of migration mode.
+
+Parameters: address of a buffer in user space to store the data (u64) to;
+           the data itself is either 0 if migration mode is disabled or 1
+           if it is enabled
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           0 in case of success.
diff --git a/Documentation/virt/kvm/devices/xics.txt b/Documentation/virt/kvm/devices/xics.txt
new file mode 100644 (file)
index 0000000..4286493
--- /dev/null
@@ -0,0 +1,66 @@
+XICS interrupt controller
+
+Device type supported: KVM_DEV_TYPE_XICS
+
+Groups:
+  KVM_DEV_XICS_SOURCES
+  Attributes: One per interrupt source, indexed by the source number.
+
+This device emulates the XICS (eXternal Interrupt Controller
+Specification) defined in PAPR.  The XICS has a set of interrupt
+sources, each identified by a 20-bit source number, and a set of
+Interrupt Control Presentation (ICP) entities, also called "servers",
+each associated with a virtual CPU.
+
+The ICP entities are created by enabling the KVM_CAP_IRQ_ARCH
+capability for each vcpu, specifying KVM_CAP_IRQ_XICS in args[0] and
+the interrupt server number (i.e. the vcpu number from the XICS's
+point of view) in args[1] of the kvm_enable_cap struct.  Each ICP has
+64 bits of state which can be read and written using the
+KVM_GET_ONE_REG and KVM_SET_ONE_REG ioctls on the vcpu.  The 64 bit
+state word has the following bitfields, starting at the
+least-significant end of the word:
+
+* Unused, 16 bits
+
+* Pending interrupt priority, 8 bits
+  Zero is the highest priority, 255 means no interrupt is pending.
+
+* Pending IPI (inter-processor interrupt) priority, 8 bits
+  Zero is the highest priority, 255 means no IPI is pending.
+
+* Pending interrupt source number, 24 bits
+  Zero means no interrupt pending, 2 means an IPI is pending
+
+* Current processor priority, 8 bits
+  Zero is the highest priority, meaning no interrupts can be
+  delivered, and 255 is the lowest priority.
+
+Each source has 64 bits of state that can be read and written using
+the KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls, specifying the
+KVM_DEV_XICS_SOURCES attribute group, with the attribute number being
+the interrupt source number.  The 64 bit state word has the following
+bitfields, starting from the least-significant end of the word:
+
+* Destination (server number), 32 bits
+  This specifies where the interrupt should be sent, and is the
+  interrupt server number specified for the destination vcpu.
+
+* Priority, 8 bits
+  This is the priority specified for this interrupt source, where 0 is
+  the highest priority and 255 is the lowest.  An interrupt with a
+  priority of 255 will never be delivered.
+
+* Level sensitive flag, 1 bit
+  This bit is 1 for a level-sensitive interrupt source, or 0 for
+  edge-sensitive (or MSI).
+
+* Masked flag, 1 bit
+  This bit is set to 1 if the interrupt is masked (cannot be delivered
+  regardless of its priority), for example by the ibm,int-off RTAS
+  call, or 0 if it is not masked.
+
+* Pending flag, 1 bit
+  This bit is 1 if the source has a pending interrupt, otherwise 0.
+
+Only one XICS instance may be created per VM.
diff --git a/Documentation/virt/kvm/devices/xive.txt b/Documentation/virt/kvm/devices/xive.txt
new file mode 100644 (file)
index 0000000..9a24a45
--- /dev/null
@@ -0,0 +1,197 @@
+POWER9 eXternal Interrupt Virtualization Engine (XIVE Gen1)
+==========================================================
+
+Device types supported:
+  KVM_DEV_TYPE_XIVE     POWER9 XIVE Interrupt Controller generation 1
+
+This device acts as a VM interrupt controller. It provides the KVM
+interface to configure the interrupt sources of a VM in the underlying
+POWER9 XIVE interrupt controller.
+
+Only one XIVE instance may be instantiated. A guest XIVE device
+requires a POWER9 host and the guest OS should have support for the
+XIVE native exploitation interrupt mode. If not, it should run using
+the legacy interrupt mode, referred as XICS (POWER7/8).
+
+* Device Mappings
+
+  The KVM device exposes different MMIO ranges of the XIVE HW which
+  are required for interrupt management. These are exposed to the
+  guest in VMAs populated with a custom VM fault handler.
+
+  1. Thread Interrupt Management Area (TIMA)
+
+  Each thread has an associated Thread Interrupt Management context
+  composed of a set of registers. These registers let the thread
+  handle priority management and interrupt acknowledgment. The most
+  important are :
+
+      - Interrupt Pending Buffer     (IPB)
+      - Current Processor Priority   (CPPR)
+      - Notification Source Register (NSR)
+
+  They are exposed to software in four different pages each proposing
+  a view with a different privilege. The first page is for the
+  physical thread context and the second for the hypervisor. Only the
+  third (operating system) and the fourth (user level) are exposed the
+  guest.
+
+  2. Event State Buffer (ESB)
+
+  Each source is associated with an Event State Buffer (ESB) with
+  either a pair of even/odd pair of pages which provides commands to
+  manage the source: to trigger, to EOI, to turn off the source for
+  instance.
+
+  3. Device pass-through
+
+  When a device is passed-through into the guest, the source
+  interrupts are from a different HW controller (PHB4) and the ESB
+  pages exposed to the guest should accommadate this change.
+
+  The passthru_irq helpers, kvmppc_xive_set_mapped() and
+  kvmppc_xive_clr_mapped() are called when the device HW irqs are
+  mapped into or unmapped from the guest IRQ number space. The KVM
+  device extends these helpers to clear the ESB pages of the guest IRQ
+  number being mapped and then lets the VM fault handler repopulate.
+  The handler will insert the ESB page corresponding to the HW
+  interrupt of the device being passed-through or the initial IPI ESB
+  page if the device has being removed.
+
+  The ESB remapping is fully transparent to the guest and the OS
+  device driver. All handling is done within VFIO and the above
+  helpers in KVM-PPC.
+
+* Groups:
+
+  1. KVM_DEV_XIVE_GRP_CTRL
+  Provides global controls on the device
+  Attributes:
+    1.1 KVM_DEV_XIVE_RESET (write only)
+    Resets the interrupt controller configuration for sources and event
+    queues. To be used by kexec and kdump.
+    Errors: none
+
+    1.2 KVM_DEV_XIVE_EQ_SYNC (write only)
+    Sync all the sources and queues and mark the EQ pages dirty. This
+    to make sure that a consistent memory state is captured when
+    migrating the VM.
+    Errors: none
+
+  2. KVM_DEV_XIVE_GRP_SOURCE (write only)
+  Initializes a new source in the XIVE device and mask it.
+  Attributes:
+    Interrupt source number  (64-bit)
+  The kvm_device_attr.addr points to a __u64 value:
+  bits:     | 63   ....  2 |   1   |   0
+  values:   |    unused    | level | type
+  - type:  0:MSI 1:LSI
+  - level: assertion level in case of an LSI.
+  Errors:
+    -E2BIG:  Interrupt source number is out of range
+    -ENOMEM: Could not create a new source block
+    -EFAULT: Invalid user pointer for attr->addr.
+    -ENXIO:  Could not allocate underlying HW interrupt
+
+  3. KVM_DEV_XIVE_GRP_SOURCE_CONFIG (write only)
+  Configures source targeting
+  Attributes:
+    Interrupt source number  (64-bit)
+  The kvm_device_attr.addr points to a __u64 value:
+  bits:     | 63   ....  33 |  32  | 31 .. 3 |  2 .. 0
+  values:   |    eisn       | mask |  server | priority
+  - priority: 0-7 interrupt priority level
+  - server: CPU number chosen to handle the interrupt
+  - mask: mask flag (unused)
+  - eisn: Effective Interrupt Source Number
+  Errors:
+    -ENOENT: Unknown source number
+    -EINVAL: Not initialized source number
+    -EINVAL: Invalid priority
+    -EINVAL: Invalid CPU number.
+    -EFAULT: Invalid user pointer for attr->addr.
+    -ENXIO:  CPU event queues not configured or configuration of the
+             underlying HW interrupt failed
+    -EBUSY:  No CPU available to serve interrupt
+
+  4. KVM_DEV_XIVE_GRP_EQ_CONFIG (read-write)
+  Configures an event queue of a CPU
+  Attributes:
+    EQ descriptor identifier (64-bit)
+  The EQ descriptor identifier is a tuple (server, priority) :
+  bits:     | 63   ....  32 | 31 .. 3 |  2 .. 0
+  values:   |    unused     |  server | priority
+  The kvm_device_attr.addr points to :
+    struct kvm_ppc_xive_eq {
+       __u32 flags;
+       __u32 qshift;
+       __u64 qaddr;
+       __u32 qtoggle;
+       __u32 qindex;
+       __u8  pad[40];
+    };
+  - flags: queue flags
+    KVM_XIVE_EQ_ALWAYS_NOTIFY (required)
+       forces notification without using the coalescing mechanism
+       provided by the XIVE END ESBs.
+  - qshift: queue size (power of 2)
+  - qaddr: real address of queue
+  - qtoggle: current queue toggle bit
+  - qindex: current queue index
+  - pad: reserved for future use
+  Errors:
+    -ENOENT: Invalid CPU number
+    -EINVAL: Invalid priority
+    -EINVAL: Invalid flags
+    -EINVAL: Invalid queue size
+    -EINVAL: Invalid queue address
+    -EFAULT: Invalid user pointer for attr->addr.
+    -EIO:    Configuration of the underlying HW failed
+
+  5. KVM_DEV_XIVE_GRP_SOURCE_SYNC (write only)
+  Synchronize the source to flush event notifications
+  Attributes:
+    Interrupt source number  (64-bit)
+  Errors:
+    -ENOENT: Unknown source number
+    -EINVAL: Not initialized source number
+
+* VCPU state
+
+  The XIVE IC maintains VP interrupt state in an internal structure
+  called the NVT. When a VP is not dispatched on a HW processor
+  thread, this structure can be updated by HW if the VP is the target
+  of an event notification.
+
+  It is important for migration to capture the cached IPB from the NVT
+  as it synthesizes the priorities of the pending interrupts. We
+  capture a bit more to report debug information.
+
+  KVM_REG_PPC_VP_STATE (2 * 64bits)
+  bits:     |  63  ....  32  |  31  ....  0  |
+  values:   |   TIMA word0   |   TIMA word1  |
+  bits:     | 127       ..........       64  |
+  values:   |            unused              |
+
+* Migration:
+
+  Saving the state of a VM using the XIVE native exploitation mode
+  should follow a specific sequence. When the VM is stopped :
+
+  1. Mask all sources (PQ=01) to stop the flow of events.
+
+  2. Sync the XIVE device with the KVM control KVM_DEV_XIVE_EQ_SYNC to
+  flush any in-flight event notification and to stabilize the EQs. At
+  this stage, the EQ pages are marked dirty to make sure they are
+  transferred in the migration sequence.
+
+  3. Capture the state of the source targeting, the EQs configuration
+  and the state of thread interrupt context registers.
+
+  Restore is similar :
+
+  1. Restore the EQ configuration. As targeting depends on it.
+  2. Restore targeting
+  3. Restore the thread interrupt contexts
+  4. Restore the source states
+  5. Let the vCPU run
diff --git a/Documentation/virt/kvm/halt-polling.txt b/Documentation/virt/kvm/halt-polling.txt
new file mode 100644 (file)
index 0000000..4f791b1
--- /dev/null
@@ -0,0 +1,136 @@
+The KVM halt polling system
+===========================
+
+The KVM halt polling system provides a feature within KVM whereby the latency
+of a guest can, under some circumstances, be reduced by polling in the host
+for some time period after the guest has elected to no longer run by cedeing.
+That is, when a guest vcpu has ceded, or in the case of powerpc when all of the
+vcpus of a single vcore have ceded, the host kernel polls for wakeup conditions
+before giving up the cpu to the scheduler in order to let something else run.
+
+Polling provides a latency advantage in cases where the guest can be run again
+very quickly by at least saving us a trip through the scheduler, normally on
+the order of a few micro-seconds, although performance benefits are workload
+dependant. In the event that no wakeup source arrives during the polling
+interval or some other task on the runqueue is runnable the scheduler is
+invoked. Thus halt polling is especially useful on workloads with very short
+wakeup periods where the time spent halt polling is minimised and the time
+savings of not invoking the scheduler are distinguishable.
+
+The generic halt polling code is implemented in:
+
+       virt/kvm/kvm_main.c: kvm_vcpu_block()
+
+The powerpc kvm-hv specific case is implemented in:
+
+       arch/powerpc/kvm/book3s_hv.c: kvmppc_vcore_blocked()
+
+Halt Polling Interval
+=====================
+
+The maximum time for which to poll before invoking the scheduler, referred to
+as the halt polling interval, is increased and decreased based on the perceived
+effectiveness of the polling in an attempt to limit pointless polling.
+This value is stored in either the vcpu struct:
+
+       kvm_vcpu->halt_poll_ns
+
+or in the case of powerpc kvm-hv, in the vcore struct:
+
+       kvmppc_vcore->halt_poll_ns
+
+Thus this is a per vcpu (or vcore) value.
+
+During polling if a wakeup source is received within the halt polling interval,
+the interval is left unchanged. In the event that a wakeup source isn't
+received during the polling interval (and thus schedule is invoked) there are
+two options, either the polling interval and total block time[0] were less than
+the global max polling interval (see module params below), or the total block
+time was greater than the global max polling interval.
+
+In the event that both the polling interval and total block time were less than
+the global max polling interval then the polling interval can be increased in
+the hope that next time during the longer polling interval the wake up source
+will be received while the host is polling and the latency benefits will be
+received. The polling interval is grown in the function grow_halt_poll_ns() and
+is multiplied by the module parameters halt_poll_ns_grow and
+halt_poll_ns_grow_start.
+
+In the event that the total block time was greater than the global max polling
+interval then the host will never poll for long enough (limited by the global
+max) to wakeup during the polling interval so it may as well be shrunk in order
+to avoid pointless polling. The polling interval is shrunk in the function
+shrink_halt_poll_ns() and is divided by the module parameter
+halt_poll_ns_shrink, or set to 0 iff halt_poll_ns_shrink == 0.
+
+It is worth noting that this adjustment process attempts to hone in on some
+steady state polling interval but will only really do a good job for wakeups
+which come at an approximately constant rate, otherwise there will be constant
+adjustment of the polling interval.
+
+[0] total block time: the time between when the halt polling function is
+                     invoked and a wakeup source received (irrespective of
+                     whether the scheduler is invoked within that function).
+
+Module Parameters
+=================
+
+The kvm module has 3 tuneable module parameters to adjust the global max
+polling interval as well as the rate at which the polling interval is grown and
+shrunk. These variables are defined in include/linux/kvm_host.h and as module
+parameters in virt/kvm/kvm_main.c, or arch/powerpc/kvm/book3s_hv.c in the
+powerpc kvm-hv case.
+
+Module Parameter       |   Description             |        Default Value
+--------------------------------------------------------------------------------
+halt_poll_ns           | The global max polling    | KVM_HALT_POLL_NS_DEFAULT
+                       | interval which defines    |
+                       | the ceiling value of the  |
+                       | polling interval for      | (per arch value)
+                       | each vcpu.                |
+--------------------------------------------------------------------------------
+halt_poll_ns_grow      | The value by which the    | 2
+                       | halt polling interval is  |
+                       | multiplied in the         |
+                       | grow_halt_poll_ns()       |
+                       | function.                 |
+--------------------------------------------------------------------------------
+halt_poll_ns_grow_start | The initial value to grow | 10000
+                       | to from zero in the       |
+                       | grow_halt_poll_ns()       |
+                       | function.                 |
+--------------------------------------------------------------------------------
+halt_poll_ns_shrink    | The value by which the    | 0
+                       | halt polling interval is  |
+                       | divided in the            |
+                       | shrink_halt_poll_ns()     |
+                       | function.                 |
+--------------------------------------------------------------------------------
+
+These module parameters can be set from the debugfs files in:
+
+       /sys/module/kvm/parameters/
+
+Note: that these module parameters are system wide values and are not able to
+      be tuned on a per vm basis.
+
+Further Notes
+=============
+
+- Care should be taken when setting the halt_poll_ns module parameter as a
+large value has the potential to drive the cpu usage to 100% on a machine which
+would be almost entirely idle otherwise. This is because even if a guest has
+wakeups during which very little work is done and which are quite far apart, if
+the period is shorter than the global max polling interval (halt_poll_ns) then
+the host will always poll for the entire block time and thus cpu utilisation
+will go to 100%.
+
+- Halt polling essentially presents a trade off between power usage and latency
+and the module parameters should be used to tune the affinity for this. Idle
+cpu time is essentially converted to host kernel time with the aim of decreasing
+latency when entering the guest.
+
+- Halt polling will only be conducted by the host when no other tasks are
+runnable on that cpu, otherwise the polling will cease immediately and
+schedule will be invoked to allow that other task to run. Thus this doesn't
+allow a guest to denial of service the cpu.
diff --git a/Documentation/virt/kvm/hypercalls.txt b/Documentation/virt/kvm/hypercalls.txt
new file mode 100644 (file)
index 0000000..5f6d291
--- /dev/null
@@ -0,0 +1,154 @@
+Linux KVM Hypercall:
+===================
+X86:
+ KVM Hypercalls have a three-byte sequence of either the vmcall or the vmmcall
+ instruction. The hypervisor can replace it with instructions that are
+ guaranteed to be supported.
+
+ Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
+ The hypercall number should be placed in rax and the return value will be
+ placed in rax.  No other registers will be clobbered unless explicitly stated
+ by the particular hypercall.
+
+S390:
+  R2-R7 are used for parameters 1-6. In addition, R1 is used for hypercall
+  number. The return value is written to R2.
+
+  S390 uses diagnose instruction as hypercall (0x500) along with hypercall
+  number in R1.
+
+  For further information on the S390 diagnose call as supported by KVM,
+  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.
+  Return value is placed in R3.
+
+  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/virt/kvm/ppc-pv.txt
+
+MIPS:
+  KVM hypercalls use the HYPCALL instruction with code 0 and the hypercall
+  number in $2 (v0). Up to four arguments may be placed in $4-$7 (a0-a3) and
+  the return value is placed in $2 (v0).
+
+KVM Hypercalls Documentation
+===========================
+The template for each hypercall is:
+1. Hypercall name.
+2. Architecture(s)
+3. Status (deprecated, obsolete, active)
+4. Purpose
+
+1. KVM_HC_VAPIC_POLL_IRQ
+------------------------
+Architecture: x86
+Status: active
+Purpose: Trigger guest exit so that the host can check for pending
+interrupts on reentry.
+
+2. KVM_HC_MMU_OP
+------------------------
+Architecture: x86
+Status: deprecated.
+Purpose: Support MMU operations such as writing to PTE,
+flushing TLB, release PT.
+
+3. KVM_HC_FEATURES
+------------------------
+Architecture: PPC
+Status: active
+Purpose: Expose hypercall availability to the guest. On x86 platforms, cpuid
+used to enumerate which hypercalls are available. On PPC, either device tree
+based lookup ( which is also what EPAPR dictates) OR KVM specific enumeration
+mechanism (which is this hypercall) can be used.
+
+4. KVM_HC_PPC_MAP_MAGIC_PAGE
+------------------------
+Architecture: PPC
+Status: active
+Purpose: To enable communication between the hypervisor and guest there is a
+shared page that contains parts of supervisor visible register state.
+The guest can map this shared page to access its supervisor register through
+memory using this hypercall.
+
+5. KVM_HC_KICK_CPU
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to wakeup a vcpu from HLT state
+Usage example : A vcpu of a paravirtualized guest that is busywaiting in guest
+kernel mode for an event to occur (ex: a spinlock to become available) can
+execute HLT instruction once it has busy-waited for more than a threshold
+time-interval. Execution of HLT instruction would cause the hypervisor to put
+the vcpu to sleep until occurrence of an appropriate event. Another vcpu of the
+same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
+specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
+is used in the hypercall for future use.
+
+
+6. KVM_HC_CLOCK_PAIRING
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to synchronize host and guest clocks.
+Usage:
+
+a0: guest physical address where host copies
+"struct kvm_clock_offset" structure.
+
+a1: clock_type, ATM only KVM_CLOCK_PAIRING_WALLCLOCK (0)
+is supported (corresponding to the host's CLOCK_REALTIME clock).
+
+               struct kvm_clock_pairing {
+                       __s64 sec;
+                       __s64 nsec;
+                       __u64 tsc;
+                       __u32 flags;
+                       __u32 pad[9];
+               };
+
+       Where:
+               * sec: seconds from clock_type clock.
+               * nsec: nanoseconds from clock_type clock.
+               * tsc: guest TSC value used to calculate sec/nsec pair
+               * flags: flags, unused (0) at the moment.
+
+The hypercall lets a guest compute a precise timestamp across
+host and guest.  The guest can use the returned TSC value to
+compute the CLOCK_REALTIME for its clock, at the same instant.
+
+Returns KVM_EOPNOTSUPP if the host does not use TSC clocksource,
+or if clock type is different than KVM_CLOCK_PAIRING_WALLCLOCK.
+
+6. KVM_HC_SEND_IPI
+------------------------
+Architecture: x86
+Status: active
+Purpose: Send IPIs to multiple vCPUs.
+
+a0: lower part of the bitmap of destination APIC IDs
+a1: higher part of the bitmap of destination APIC IDs
+a2: the lowest APIC ID in bitmap
+a3: APIC ICR
+
+The hypercall lets a guest send multicast IPIs, with at most 128
+128 destinations per hypercall in 64-bit mode and 64 vCPUs per
+hypercall in 32-bit mode.  The destinations are represented by a
+bitmap contained in the first two arguments (a0 and a1). Bit 0 of
+a0 corresponds to the APIC ID in the third argument (a2), bit 1
+corresponds to the APIC ID a2+1, and so on.
+
+Returns the number of CPUs to which the IPIs were delivered successfully.
+
+7. KVM_HC_SCHED_YIELD
+------------------------
+Architecture: x86
+Status: active
+Purpose: Hypercall used to yield if the IPI target vCPU is preempted
+
+a0: destination APIC ID
+
+Usage example: When sending a call-function IPI-many to vCPUs, yield if
+any of the IPI target vCPUs was preempted.
diff --git a/Documentation/virt/kvm/index.rst b/Documentation/virt/kvm/index.rst
new file mode 100644 (file)
index 0000000..ada224a
--- /dev/null
@@ -0,0 +1,12 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===
+KVM
+===
+
+.. toctree::
+   :maxdepth: 2
+
+   amd-memory-encryption
+   cpuid
+   vcpu-requests
diff --git a/Documentation/virt/kvm/locking.txt b/Documentation/virt/kvm/locking.txt
new file mode 100644 (file)
index 0000000..635cd6e
--- /dev/null
@@ -0,0 +1,215 @@
+KVM Lock Overview
+=================
+
+1. Acquisition Orders
+---------------------
+
+The acquisition orders for mutexes are as follows:
+
+- kvm->lock is taken outside vcpu->mutex
+
+- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock
+
+- kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
+  them together is quite rare.
+
+On x86, vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock.
+
+Everything else is a leaf: no other lock is taken inside the critical
+sections.
+
+2: Exception
+------------
+
+Fast page fault:
+
+Fast page fault is the fast path which fixes the guest page fault out of
+the mmu-lock on x86. Currently, the page fault can be fast in one of the
+following two cases:
+
+1. Access Tracking: The SPTE is not present, but it is marked for access
+tracking i.e. the SPTE_SPECIAL_MASK is set. That means we need to
+restore the saved R/X bits. This is described in more detail later below.
+
+2. Write-Protection: The SPTE is present and the fault is
+caused by write-protect. That means we just need to change the W bit of the 
+spte.
+
+What we use to avoid all the race is the SPTE_HOST_WRITEABLE bit and
+SPTE_MMU_WRITEABLE bit on the spte:
+- SPTE_HOST_WRITEABLE means the gfn is writable on host.
+- SPTE_MMU_WRITEABLE means the gfn is writable on mmu. The bit is set when
+  the gfn is writable on guest mmu and it is not write-protected by shadow
+  page write-protection.
+
+On fast page fault path, we will use cmpxchg to atomically set the spte W
+bit if spte.SPTE_HOST_WRITEABLE = 1 and spte.SPTE_WRITE_PROTECT = 1, or 
+restore the saved R/X bits if VMX_EPT_TRACK_ACCESS mask is set, or both. This
+is safe because whenever changing these bits can be detected by cmpxchg.
+
+But we need carefully check these cases:
+1): The mapping from gfn to pfn
+The mapping from gfn to pfn may be changed since we can only ensure the pfn
+is not changed during cmpxchg. This is a ABA problem, for example, below case
+will happen:
+
+At the beginning:
+gpte = gfn1
+gfn1 is mapped to pfn1 on host
+spte is the shadow page table entry corresponding with gpte and
+spte = pfn1
+
+   VCPU 0                           VCPU0
+on fast page fault path:
+
+   old_spte = *spte;
+                                 pfn1 is swapped out:
+                                    spte = 0;
+
+                                 pfn1 is re-alloced for gfn2.
+
+                                 gpte is changed to point to
+                                 gfn2 by the guest:
+                                    spte = pfn1;
+
+   if (cmpxchg(spte, old_spte, old_spte+W)
+       mark_page_dirty(vcpu->kvm, gfn1)
+             OOPS!!!
+
+We dirty-log for gfn1, that means gfn2 is lost in dirty-bitmap.
+
+For direct sp, we can easily avoid it since the spte of direct sp is fixed
+to gfn. For indirect sp, before we do cmpxchg, we call gfn_to_pfn_atomic()
+to pin gfn to pfn, because after gfn_to_pfn_atomic():
+- We have held the refcount of pfn that means the pfn can not be freed and
+  be reused for another gfn.
+- The pfn is writable that means it can not be shared between different gfns
+  by KSM.
+
+Then, we can ensure the dirty bitmaps is correctly set for a gfn.
+
+Currently, to simplify the whole things, we disable fast page fault for
+indirect shadow page.
+
+2): Dirty bit tracking
+In the origin code, the spte can be fast updated (non-atomically) if the
+spte is read-only and the Accessed bit has already been set since the
+Accessed bit and Dirty bit can not be lost.
+
+But it is not true after fast page fault since the spte can be marked
+writable between reading spte and updating spte. Like below case:
+
+At the beginning:
+spte.W = 0
+spte.Accessed = 1
+
+   VCPU 0                                       VCPU0
+In mmu_spte_clear_track_bits():
+
+   old_spte = *spte;
+
+   /* 'if' condition is satisfied. */
+   if (old_spte.Accessed == 1 &&
+        old_spte.W == 0)
+      spte = 0ull;
+                                         on fast page fault path:
+                                             spte.W = 1
+                                         memory write on the spte:
+                                             spte.Dirty = 1
+
+
+   else
+      old_spte = xchg(spte, 0ull)
+
+
+   if (old_spte.Accessed == 1)
+      kvm_set_pfn_accessed(spte.pfn);
+   if (old_spte.Dirty == 1)
+      kvm_set_pfn_dirty(spte.pfn);
+      OOPS!!!
+
+The Dirty bit is lost in this case.
+
+In order to avoid this kind of issue, we always treat the spte as "volatile"
+if it can be updated out of mmu-lock, see spte_has_volatile_bits(), it means,
+the spte is always atomically updated in this case.
+
+3): flush tlbs due to spte updated
+If the spte is updated from writable to readonly, we should flush all TLBs,
+otherwise rmap_write_protect will find a read-only spte, even though the
+writable spte might be cached on a CPU's TLB.
+
+As mentioned before, the spte can be updated to writable out of mmu-lock on
+fast page fault path, in order to easily audit the path, we see if TLBs need
+be flushed caused by this reason in mmu_spte_update() since this is a common
+function to update spte (present -> present).
+
+Since the spte is "volatile" if it can be updated out of mmu-lock, we always
+atomically update the spte, the race caused by fast page fault can be avoided,
+See the comments in spte_has_volatile_bits() and mmu_spte_update().
+
+Lockless Access Tracking:
+
+This is used for Intel CPUs that are using EPT but do not support the EPT A/D
+bits. In this case, when the KVM MMU notifier is called to track accesses to a
+page (via kvm_mmu_notifier_clear_flush_young), it marks the PTE as not-present
+by clearing the RWX bits in the PTE and storing the original R & X bits in
+some unused/ignored bits. In addition, the SPTE_SPECIAL_MASK is also set on the
+PTE (using the ignored bit 62). When the VM tries to access the page later on,
+a fault is generated and the fast page fault mechanism described above is used
+to atomically restore the PTE to a Present state. The W bit is not saved when
+the PTE is marked for access tracking and during restoration to the Present
+state, the W bit is set depending on whether or not it was a write access. If
+it wasn't, then the W bit will remain clear until a write access happens, at 
+which time it will be set using the Dirty tracking mechanism described above.
+
+3. Reference
+------------
+
+Name:          kvm_lock
+Type:          mutex
+Arch:          any
+Protects:      - vm_list
+
+Name:          kvm_count_lock
+Type:          raw_spinlock_t
+Arch:          any
+Protects:      - hardware virtualization enable/disable
+Comment:       'raw' because hardware enabling/disabling must be atomic /wrt
+               migration.
+
+Name:          kvm_arch::tsc_write_lock
+Type:          raw_spinlock
+Arch:          x86
+Protects:      - kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
+               - tsc offset in vmcb
+Comment:       'raw' because updating the tsc offsets must not be preempted.
+
+Name:          kvm->mmu_lock
+Type:          spinlock_t
+Arch:          any
+Protects:      -shadow page/shadow tlb entry
+Comment:       it is a spinlock since it is used in mmu notifier.
+
+Name:          kvm->srcu
+Type:          srcu lock
+Arch:          any
+Protects:      - kvm->memslots
+               - kvm->buses
+Comment:       The srcu read lock must be held while accessing memslots (e.g.
+               when using gfn_to_* functions) and while accessing in-kernel
+               MMIO/PIO address->device structure mapping (kvm->buses).
+               The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
+               if it is needed by multiple functions.
+
+Name:          blocked_vcpu_on_cpu_lock
+Type:          spinlock_t
+Arch:          x86
+Protects:      blocked_vcpu_on_cpu
+Comment:       This is a per-CPU lock and it is used for VT-d posted-interrupts.
+               When VT-d posted-interrupts is supported and the VM has assigned
+               devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
+               protected by blocked_vcpu_on_cpu_lock, when VT-d hardware issues
+               wakeup notification event since external interrupts from the
+               assigned devices happens, we will find the vCPU on the list to
+               wakeup.
diff --git a/Documentation/virt/kvm/mmu.txt b/Documentation/virt/kvm/mmu.txt
new file mode 100644 (file)
index 0000000..1b9880d
--- /dev/null
@@ -0,0 +1,449 @@
+The x86 kvm shadow mmu
+======================
+
+The mmu (in arch/x86/kvm, files mmu.[ch] and paging_tmpl.h) is responsible
+for presenting a standard x86 mmu to the guest, while translating guest
+physical addresses to host physical addresses.
+
+The mmu code attempts to satisfy the following requirements:
+
+- correctness: the guest should not be able to determine that it is running
+               on an emulated mmu except for timing (we attempt to comply
+               with the specification, not emulate the characteristics of
+               a particular implementation such as tlb size)
+- security:    the guest must not be able to touch host memory not assigned
+               to it
+- performance: minimize the performance penalty imposed by the mmu
+- scaling:     need to scale to large memory and large vcpu guests
+- hardware:    support the full range of x86 virtualization hardware
+- integration: Linux memory management code must be in control of guest memory
+               so that swapping, page migration, page merging, transparent
+               hugepages, and similar features work without change
+- dirty tracking: report writes to guest memory to enable live migration
+               and framebuffer-based displays
+- footprint:   keep the amount of pinned kernel memory low (most memory
+               should be shrinkable)
+- reliability:  avoid multipage or GFP_ATOMIC allocations
+
+Acronyms
+========
+
+pfn   host page frame number
+hpa   host physical address
+hva   host virtual address
+gfn   guest frame number
+gpa   guest physical address
+gva   guest virtual address
+ngpa  nested guest physical address
+ngva  nested guest virtual address
+pte   page table entry (used also to refer generically to paging structure
+      entries)
+gpte  guest pte (referring to gfns)
+spte  shadow pte (referring to pfns)
+tdp   two dimensional paging (vendor neutral term for NPT and EPT)
+
+Virtual and real hardware supported
+===================================
+
+The mmu supports first-generation mmu hardware, which allows an atomic switch
+of the current paging mode and cr3 during guest entry, as well as
+two-dimensional paging (AMD's NPT and Intel's EPT).  The emulated hardware
+it exposes is the traditional 2/3/4 level x86 mmu, with support for global
+pages, pae, pse, pse36, cr0.wp, and 1GB pages. Emulated hardware also
+able to expose NPT capable hardware on NPT capable hosts.
+
+Translation
+===========
+
+The primary job of the mmu is to program the processor's mmu to translate
+addresses for the guest.  Different translations are required at different
+times:
+
+- when guest paging is disabled, we translate guest physical addresses to
+  host physical addresses (gpa->hpa)
+- when guest paging is enabled, we translate guest virtual addresses, to
+  guest physical addresses, to host physical addresses (gva->gpa->hpa)
+- when the guest launches a guest of its own, we translate nested guest
+  virtual addresses, to nested guest physical addresses, to guest physical
+  addresses, to host physical addresses (ngva->ngpa->gpa->hpa)
+
+The primary challenge is to encode between 1 and 3 translations into hardware
+that support only 1 (traditional) and 2 (tdp) translations.  When the
+number of required translations matches the hardware, the mmu operates in
+direct mode; otherwise it operates in shadow mode (see below).
+
+Memory
+======
+
+Guest memory (gpa) is part of the user address space of the process that is
+using kvm.  Userspace defines the translation between guest addresses and user
+addresses (gpa->hva); note that two gpas may alias to the same hva, but not
+vice versa.
+
+These hvas may be backed using any method available to the host: anonymous
+memory, file backed memory, and device memory.  Memory might be paged by the
+host at any time.
+
+Events
+======
+
+The mmu is driven by events, some from the guest, some from the host.
+
+Guest generated events:
+- writes to control registers (especially cr3)
+- invlpg/invlpga instruction execution
+- access to missing or protected translations
+
+Host generated events:
+- changes in the gpa->hpa translation (either through gpa->hva changes or
+  through hva->hpa changes)
+- memory pressure (the shrinker)
+
+Shadow pages
+============
+
+The principal data structure is the shadow page, 'struct kvm_mmu_page'.  A
+shadow page contains 512 sptes, which can be either leaf or nonleaf sptes.  A
+shadow page may contain a mix of leaf and nonleaf sptes.
+
+A nonleaf spte allows the hardware mmu to reach the leaf pages and
+is not related to a translation directly.  It points to other shadow pages.
+
+A leaf spte corresponds to either one or two translations encoded into
+one paging structure entry.  These are always the lowest level of the
+translation stack, with optional higher level translations left to NPT/EPT.
+Leaf ptes point at guest pages.
+
+The following table shows translations encoded by leaf ptes, with higher-level
+translations in parentheses:
+
+ Non-nested guests:
+  nonpaging:     gpa->hpa
+  paging:        gva->gpa->hpa
+  paging, tdp:   (gva->)gpa->hpa
+ Nested guests:
+  non-tdp:       ngva->gpa->hpa  (*)
+  tdp:           (ngva->)ngpa->gpa->hpa
+
+(*) the guest hypervisor will encode the ngva->gpa translation into its page
+    tables if npt is not present
+
+Shadow pages contain the following information:
+  role.level:
+    The level in the shadow paging hierarchy that this shadow page belongs to.
+    1=4k sptes, 2=2M sptes, 3=1G sptes, etc.
+  role.direct:
+    If set, leaf sptes reachable from this page are for a linear range.
+    Examples include real mode translation, large guest pages backed by small
+    host pages, and gpa->hpa translations when NPT or EPT is active.
+    The linear range starts at (gfn << PAGE_SHIFT) and its size is determined
+    by role.level (2MB for first level, 1GB for second level, 0.5TB for third
+    level, 256TB for fourth level)
+    If clear, this page corresponds to a guest page table denoted by the gfn
+    field.
+  role.quadrant:
+    When role.gpte_is_8_bytes=0, the guest uses 32-bit gptes while the host uses 64-bit
+    sptes.  That means a guest page table contains more ptes than the host,
+    so multiple shadow pages are needed to shadow one guest page.
+    For first-level shadow pages, role.quadrant can be 0 or 1 and denotes the
+    first or second 512-gpte block in the guest page table.  For second-level
+    page tables, each 32-bit gpte is converted to two 64-bit sptes
+    (since each first-level guest page is shadowed by two first-level
+    shadow pages) so role.quadrant takes values in the range 0..3.  Each
+    quadrant maps 1GB virtual address space.
+  role.access:
+    Inherited guest access permissions in the form uwx.  Note execute
+    permission is positive, not negative.
+  role.invalid:
+    The page is invalid and should not be used.  It is a root page that is
+    currently pinned (by a cpu hardware register pointing to it); once it is
+    unpinned it will be destroyed.
+  role.gpte_is_8_bytes:
+    Reflects the size of the guest PTE for which the page is valid, i.e. '1'
+    if 64-bit gptes are in use, '0' if 32-bit gptes are in use.
+  role.nxe:
+    Contains the value of efer.nxe for which the page is valid.
+  role.cr0_wp:
+    Contains the value of cr0.wp for which the page is valid.
+  role.smep_andnot_wp:
+    Contains the value of cr4.smep && !cr0.wp for which the page is valid
+    (pages for which this is true are different from other pages; see the
+    treatment of cr0.wp=0 below).
+  role.smap_andnot_wp:
+    Contains the value of cr4.smap && !cr0.wp for which the page is valid
+    (pages for which this is true are different from other pages; see the
+    treatment of cr0.wp=0 below).
+  role.ept_sp:
+    This is a virtual flag to denote a shadowed nested EPT page.  ept_sp
+    is true if "cr0_wp && smap_andnot_wp", an otherwise invalid combination.
+  role.smm:
+    Is 1 if the page is valid in system management mode.  This field
+    determines which of the kvm_memslots array was used to build this
+    shadow page; it is also used to go back from a struct kvm_mmu_page
+    to a memslot, through the kvm_memslots_for_spte_role macro and
+    __gfn_to_memslot.
+  role.ad_disabled:
+    Is 1 if the MMU instance cannot use A/D bits.  EPT did not have A/D
+    bits before Haswell; shadow EPT page tables also cannot use A/D bits
+    if the L1 hypervisor does not enable them.
+  gfn:
+    Either the guest page table containing the translations shadowed by this
+    page, or the base page frame for linear translations.  See role.direct.
+  spt:
+    A pageful of 64-bit sptes containing the translations for this page.
+    Accessed by both kvm and hardware.
+    The page pointed to by spt will have its page->private pointing back
+    at the shadow page structure.
+    sptes in spt point either at guest pages, or at lower-level shadow pages.
+    Specifically, if sp1 and sp2 are shadow pages, then sp1->spt[n] may point
+    at __pa(sp2->spt).  sp2 will point back at sp1 through parent_pte.
+    The spt array forms a DAG structure with the shadow page as a node, and
+    guest pages as leaves.
+  gfns:
+    An array of 512 guest frame numbers, one for each present pte.  Used to
+    perform a reverse map from a pte to a gfn. When role.direct is set, any
+    element of this array can be calculated from the gfn field when used, in
+    this case, the array of gfns is not allocated. See role.direct and gfn.
+  root_count:
+    A counter keeping track of how many hardware registers (guest cr3 or
+    pdptrs) are now pointing at the page.  While this counter is nonzero, the
+    page cannot be destroyed.  See role.invalid.
+  parent_ptes:
+    The reverse mapping for the pte/ptes pointing at this page's spt. If
+    parent_ptes bit 0 is zero, only one spte points at this page and
+    parent_ptes points at this single spte, otherwise, there exists multiple
+    sptes pointing at this page and (parent_ptes & ~0x1) points at a data
+    structure with a list of parent sptes.
+  unsync:
+    If true, then the translations in this page may not match the guest's
+    translation.  This is equivalent to the state of the tlb when a pte is
+    changed but before the tlb entry is flushed.  Accordingly, unsync ptes
+    are synchronized when the guest executes invlpg or flushes its tlb by
+    other means.  Valid for leaf pages.
+  unsync_children:
+    How many sptes in the page point at pages that are unsync (or have
+    unsynchronized children).
+  unsync_child_bitmap:
+    A bitmap indicating which sptes in spt point (directly or indirectly) at
+    pages that may be unsynchronized.  Used to quickly locate all unsychronized
+    pages reachable from a given page.
+  clear_spte_count:
+    Only present on 32-bit hosts, where a 64-bit spte cannot be written
+    atomically.  The reader uses this while running out of the MMU lock
+    to detect in-progress updates and retry them until the writer has
+    finished the write.
+  write_flooding_count:
+    A guest may write to a page table many times, causing a lot of
+    emulations if the page needs to be write-protected (see "Synchronized
+    and unsynchronized pages" below).  Leaf pages can be unsynchronized
+    so that they do not trigger frequent emulation, but this is not
+    possible for non-leafs.  This field counts the number of emulations
+    since the last time the page table was actually used; if emulation
+    is triggered too frequently on this page, KVM will unmap the page
+    to avoid emulation in the future.
+
+Reverse map
+===========
+
+The mmu maintains a reverse mapping whereby all ptes mapping a page can be
+reached given its gfn.  This is used, for example, when swapping out a page.
+
+Synchronized and unsynchronized pages
+=====================================
+
+The guest uses two events to synchronize its tlb and page tables: tlb flushes
+and page invalidations (invlpg).
+
+A tlb flush means that we need to synchronize all sptes reachable from the
+guest's cr3.  This is expensive, so we keep all guest page tables write
+protected, and synchronize sptes to gptes when a gpte is written.
+
+A special case is when a guest page table is reachable from the current
+guest cr3.  In this case, the guest is obliged to issue an invlpg instruction
+before using the translation.  We take advantage of that by removing write
+protection from the guest page, and allowing the guest to modify it freely.
+We synchronize modified gptes when the guest invokes invlpg.  This reduces
+the amount of emulation we have to do when the guest modifies multiple gptes,
+or when the a guest page is no longer used as a page table and is used for
+random guest data.
+
+As a side effect we have to resynchronize all reachable unsynchronized shadow
+pages on a tlb flush.
+
+
+Reaction to events
+==================
+
+- guest page fault (or npt page fault, or ept violation)
+
+This is the most complicated event.  The cause of a page fault can be:
+
+  - a true guest fault (the guest translation won't allow the access) (*)
+  - access to a missing translation
+  - access to a protected translation
+    - when logging dirty pages, memory is write protected
+    - synchronized shadow pages are write protected (*)
+  - access to untranslatable memory (mmio)
+
+  (*) not applicable in direct mode
+
+Handling a page fault is performed as follows:
+
+ - if the RSV bit of the error code is set, the page fault is caused by guest
+   accessing MMIO and cached MMIO information is available.
+   - walk shadow page table
+   - check for valid generation number in the spte (see "Fast invalidation of
+     MMIO sptes" below)
+   - cache the information to vcpu->arch.mmio_gva, vcpu->arch.access and
+     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/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
+ - determine the host page
+   - if this is an mmio request, there is no host page; cache the info to
+     vcpu->arch.mmio_gva, vcpu->arch.access and vcpu->arch.mmio_gfn
+ - walk the shadow page table to find the spte for the translation,
+   instantiating missing intermediate page tables as necessary
+   - If this is an mmio request, cache the mmio info to the spte and set some
+     reserved bit on the spte (see callers of kvm_mmu_set_mmio_spte_mask)
+ - try to unsynchronize the page
+   - if successful, we can let the guest continue and modify the gpte
+ - emulate the instruction
+   - if failed, unshadow the page and let the guest continue
+ - update any translations that were modified by the instruction
+
+invlpg handling:
+
+  - walk the shadow page hierarchy and drop affected translations
+  - try to reinstantiate the indicated translation in the hope that the
+    guest will use it in the near future
+
+Guest control register updates:
+
+- mov to cr3
+  - look up new shadow roots
+  - synchronize newly reachable shadow pages
+
+- mov to cr0/cr4/efer
+  - set up mmu context for new paging mode
+  - look up new shadow roots
+  - synchronize newly reachable shadow pages
+
+Host translation updates:
+
+  - mmu notifier called with updated hva
+  - look up affected sptes through reverse map
+  - drop (or update) translations
+
+Emulating cr0.wp
+================
+
+If tdp is not enabled, the host must keep cr0.wp=1 so page write protection
+works for the guest kernel, not guest guest userspace.  When the guest
+cr0.wp=1, this does not present a problem.  However when the guest cr0.wp=0,
+we cannot map the permissions for gpte.u=1, gpte.w=0 to any spte (the
+semantics require allowing any guest kernel access plus user read access).
+
+We handle this by mapping the permissions to two possible sptes, depending
+on fault type:
+
+- kernel write fault: spte.u=0, spte.w=1 (allows full kernel access,
+  disallows user access)
+- read fault: spte.u=1, spte.w=0 (allows full read access, disallows kernel
+  write access)
+
+(user write faults generate a #PF)
+
+In the first case there are two additional complications:
+- if CR4.SMEP is enabled: since we've turned the page into a kernel page,
+  the kernel may now execute it.  We handle this by also setting spte.nx.
+  If we get a user fetch or read fault, we'll change spte.u=1 and
+  spte.nx=gpte.nx back.  For this to work, KVM forces EFER.NX to 1 when
+  shadow paging is in use.
+- if CR4.SMAP is disabled: since the page has been changed to a kernel
+  page, it can not be reused when CR4.SMAP is enabled. We set
+  CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
+  here we do not care the case that CR4.SMAP is enabled since KVM will
+  directly inject #PF to guest due to failed permission check.
+
+To prevent an spte that was converted into a kernel page with cr0.wp=0
+from being written by the kernel after cr0.wp has changed to 1, we make
+the value of cr0.wp part of the page role.  This means that an spte created
+with one value of cr0.wp cannot be used when cr0.wp has a different value -
+it will simply be missed by the shadow page lookup code.  A similar issue
+exists when an spte created with cr0.wp=0 and cr4.smep=0 is used after
+changing cr4.smep to 1.  To avoid this, the value of !cr0.wp && cr4.smep
+is also made a part of the page role.
+
+Large pages
+===========
+
+The mmu supports all combinations of large and small guest and host pages.
+Supported page sizes include 4k, 2M, 4M, and 1G.  4M pages are treated as
+two separate 2M pages, on both guest and host, since the mmu always uses PAE
+paging.
+
+To instantiate a large spte, four constraints must be satisfied:
+
+- the spte must point to a large host page
+- the guest pte must be a large pte of at least equivalent size (if tdp is
+  enabled, there is no guest pte and this condition is satisfied)
+- if the spte will be writeable, the large page frame may not overlap any
+  write-protected pages
+- the guest page must be wholly contained by a single memory slot
+
+To check the last two conditions, the mmu maintains a ->disallow_lpage set of
+arrays for each memory slot and large page size.  Every write protected page
+causes its disallow_lpage to be incremented, thus preventing instantiation of
+a large spte.  The frames at the end of an unaligned memory slot have
+artificially inflated ->disallow_lpages so they can never be instantiated.
+
+Fast invalidation of MMIO sptes
+===============================
+
+As mentioned in "Reaction to events" above, kvm will cache MMIO
+information in leaf sptes.  When a new memslot is added or an existing
+memslot is changed, this information may become stale and needs to be
+invalidated.  This also needs to hold the MMU lock while walking all
+shadow pages, and is made more scalable with a similar technique.
+
+MMIO sptes have a few spare bits, which are used to store a
+generation number.  The global generation number is stored in
+kvm_memslots(kvm)->generation, and increased whenever guest memory info
+changes.
+
+When KVM finds an MMIO spte, it checks the generation number of the spte.
+If the generation number of the spte does not equal the global generation
+number, it will ignore the cached MMIO information and handle the page
+fault through the slow path.
+
+Since only 19 bits are used to store generation-number on mmio spte, all
+pages are zapped when there is an overflow.
+
+Unfortunately, a single memory access might access kvm_memslots(kvm) multiple
+times, the last one happening when the generation number is retrieved and
+stored into the MMIO spte.  Thus, the MMIO spte might be created based on
+out-of-date information, but with an up-to-date generation number.
+
+To avoid this, the generation number is incremented again after synchronize_srcu
+returns; thus, bit 63 of kvm_memslots(kvm)->generation set to 1 only during a
+memslot update, while some SRCU readers might be using the old copy.  We do not
+want to use an MMIO sptes created with an odd generation number, and we can do
+this without losing a bit in the MMIO spte.  The "update in-progress" bit of the
+generation is not stored in MMIO spte, and is so is implicitly zero when the
+generation is extracted out of the spte.  If KVM is unlucky and creates an MMIO
+spte while an update is in-progress, the next access to the spte will always be
+a cache miss.  For example, a subsequent access during the update window will
+miss due to the in-progress flag diverging, while an access after the update
+window closes will have a higher generation number (as compared to the spte).
+
+
+Further reading
+===============
+
+- NPT presentation from KVM Forum 2008
+  http://www.linux-kvm.org/images/c/c8/KvmForum2008%24kdf2008_21.pdf
+
diff --git a/Documentation/virt/kvm/msr.txt b/Documentation/virt/kvm/msr.txt
new file mode 100644 (file)
index 0000000..df1f433
--- /dev/null
@@ -0,0 +1,284 @@
+KVM-specific MSRs.
+Glauber Costa <glommer@redhat.com>, Red Hat Inc, 2010
+=====================================================
+
+KVM makes use of some custom MSRs to service some requests.
+
+Custom MSRs have a range reserved for them, that goes from
+0x4b564d00 to 0x4b564dff. There are MSRs outside this area,
+but they are deprecated and their use is discouraged.
+
+Custom MSR list
+--------
+
+The current supported Custom MSR list is:
+
+MSR_KVM_WALL_CLOCK_NEW:   0x4b564d00
+
+       data: 4-byte alignment physical address of a memory area which must be
+       in guest RAM. This memory is expected to hold a copy of the following
+       structure:
+
+       struct pvclock_wall_clock {
+               u32   version;
+               u32   sec;
+               u32   nsec;
+       } __attribute__((__packed__));
+
+       whose data will be filled in by the hypervisor. The hypervisor is only
+       guaranteed to update this data at the moment of MSR write.
+       Users that want to reliably query this information more than once have
+       to write more than once to this MSR. Fields have the following meanings:
+
+               version: guest has to check version before and after grabbing
+               time information and check that they are both equal and even.
+               An odd version indicates an in-progress update.
+
+               sec: number of seconds for wallclock at time of boot.
+
+               nsec: number of nanoseconds for wallclock at time of boot.
+
+       In order to get the current wallclock time, the system_time from
+       MSR_KVM_SYSTEM_TIME_NEW needs to be added.
+
+       Note that although MSRs are per-CPU entities, the effect of this
+       particular MSR is global.
+
+       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
+       leaf prior to usage.
+
+MSR_KVM_SYSTEM_TIME_NEW:  0x4b564d01
+
+       data: 4-byte aligned physical address of a memory area which must be in
+       guest RAM, plus an enable bit in bit 0. This memory is expected to hold
+       a copy of the following structure:
+
+       struct pvclock_vcpu_time_info {
+               u32   version;
+               u32   pad0;
+               u64   tsc_timestamp;
+               u64   system_time;
+               u32   tsc_to_system_mul;
+               s8    tsc_shift;
+               u8    flags;
+               u8    pad[2];
+       } __attribute__((__packed__)); /* 32 bytes */
+
+       whose data will be filled in by the hypervisor periodically. Only one
+       write, or registration, is needed for each VCPU. The interval between
+       updates of this structure is arbitrary and implementation-dependent.
+       The hypervisor may update this structure at any time it sees fit until
+       anything with bit0 == 0 is written to it.
+
+       Fields have the following meanings:
+
+               version: guest has to check version before and after grabbing
+               time information and check that they are both equal and even.
+               An odd version indicates an in-progress update.
+
+               tsc_timestamp: the tsc value at the current VCPU at the time
+               of the update of this structure. Guests can subtract this value
+               from current tsc to derive a notion of elapsed time since the
+               structure update.
+
+               system_time: a host notion of monotonic time, including sleep
+               time at the time this structure was last updated. Unit is
+               nanoseconds.
+
+               tsc_to_system_mul: multiplier to be used when converting
+               tsc-related quantity to nanoseconds
+
+               tsc_shift: shift to be used when converting tsc-related
+               quantity to nanoseconds. This shift will ensure that
+               multiplication with tsc_to_system_mul does not overflow.
+               A positive value denotes a left shift, a negative value
+               a right shift.
+
+               The conversion from tsc to nanoseconds involves an additional
+               right shift by 32 bits. With this information, guests can
+               derive per-CPU time by doing:
+
+                       time = (current_tsc - tsc_timestamp)
+                       if (tsc_shift >= 0)
+                               time <<= tsc_shift;
+                       else
+                               time >>= -tsc_shift;
+                       time = (time * tsc_to_system_mul) >> 32
+                       time = time + system_time
+
+               flags: bits in this field indicate extended capabilities
+               coordinated between the guest and the hypervisor. Availability
+               of specific flags has to be checked in 0x40000001 cpuid leaf.
+               Current flags are:
+
+                flag bit   | cpuid bit    | meaning
+               -------------------------------------------------------------
+                           |              | time measures taken across
+                    0      |      24      | multiple cpus are guaranteed to
+                           |              | be monotonic
+               -------------------------------------------------------------
+                           |              | guest vcpu has been paused by
+                    1      |     N/A      | the host
+                           |              | See 4.70 in api.txt
+               -------------------------------------------------------------
+
+       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
+       leaf prior to usage.
+
+
+MSR_KVM_WALL_CLOCK:  0x11
+
+       data and functioning: same as MSR_KVM_WALL_CLOCK_NEW. Use that instead.
+
+       This MSR falls outside the reserved KVM range and may be removed in the
+       future. Its usage is deprecated.
+
+       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
+       leaf prior to usage.
+
+MSR_KVM_SYSTEM_TIME: 0x12
+
+       data and functioning: same as MSR_KVM_SYSTEM_TIME_NEW. Use that instead.
+
+       This MSR falls outside the reserved KVM range and may be removed in the
+       future. Its usage is deprecated.
+
+       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
+       leaf prior to usage.
+
+       The suggested algorithm for detecting kvmclock presence is then:
+
+               if (!kvm_para_available())    /* refer to cpuid.txt */
+                       return NON_PRESENT;
+
+               flags = cpuid_eax(0x40000001);
+               if (flags & 3) {
+                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
+                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
+                       return PRESENT;
+               } else if (flags & 0) {
+                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
+                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
+                       return PRESENT;
+               } else
+                       return NON_PRESENT;
+
+MSR_KVM_ASYNC_PF_EN: 0x4b564d02
+       data: Bits 63-6 hold 64-byte aligned physical address of a
+       64 byte memory area which must be in guest RAM and must be
+       zeroed. Bits 5-3 are reserved and should be zero. Bit 0 is 1
+       when asynchronous page faults are enabled on the vcpu 0 when
+       disabled. Bit 1 is 1 if asynchronous page faults can be injected
+       when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
+       are delivered to L1 as #PF vmexits.  Bit 2 can be set only if
+       KVM_FEATURE_ASYNC_PF_VMEXIT is present in CPUID.
+
+       First 4 byte of 64 byte memory location will be written to by
+       the hypervisor at the time of asynchronous page fault (APF)
+       injection to indicate type of asynchronous page fault. Value
+       of 1 means that the page referred to by the page fault is not
+       present. Value 2 means that the page is now available. Disabling
+       interrupt inhibits APFs. Guest must not enable interrupt
+       before the reason is read, or it may be overwritten by another
+       APF. Since APF uses the same exception vector as regular page
+       fault guest must reset the reason to 0 before it does
+       something that can generate normal page fault.  If during page
+       fault APF reason is 0 it means that this is regular page
+       fault.
+
+       During delivery of type 1 APF cr2 contains a token that will
+       be used to notify a guest when missing page becomes
+       available. When page becomes available type 2 APF is sent with
+       cr2 set to the token associated with the page. There is special
+       kind of token 0xffffffff which tells vcpu that it should wake
+       up all processes waiting for APFs and no individual type 2 APFs
+       will be sent.
+
+       If APF is disabled while there are outstanding APFs, they will
+       not be delivered.
+
+       Currently type 2 APF will be always delivered on the same vcpu as
+       type 1 was, but guest should not rely on that.
+
+MSR_KVM_STEAL_TIME: 0x4b564d03
+
+       data: 64-byte alignment physical address of a memory area which must be
+       in guest RAM, plus an enable bit in bit 0. This memory is expected to
+       hold a copy of the following structure:
+
+       struct kvm_steal_time {
+               __u64 steal;
+               __u32 version;
+               __u32 flags;
+               __u8  preempted;
+               __u8  u8_pad[3];
+               __u32 pad[11];
+       }
+
+       whose data will be filled in by the hypervisor periodically. Only one
+       write, or registration, is needed for each VCPU. The interval between
+       updates of this structure is arbitrary and implementation-dependent.
+       The hypervisor may update this structure at any time it sees fit until
+       anything with bit0 == 0 is written to it. Guest is required to make sure
+       this structure is initialized to zero.
+
+       Fields have the following meanings:
+
+               version: a sequence counter. In other words, guest has to check
+               this field before and after grabbing time information and make
+               sure they are both equal and even. An odd version indicates an
+               in-progress update.
+
+               flags: At this point, always zero. May be used to indicate
+               changes in this structure in the future.
+
+               steal: the amount of time in which this vCPU did not run, in
+               nanoseconds. Time during which the vcpu is idle, will not be
+               reported as steal time.
+
+               preempted: indicate the vCPU who owns this struct is running or
+               not. Non-zero values mean the vCPU has been preempted. Zero
+               means the vCPU is not preempted. NOTE, it is always zero if the
+               the hypervisor doesn't support this field.
+
+MSR_KVM_EOI_EN: 0x4b564d04
+       data: Bit 0 is 1 when PV end of interrupt is enabled on the vcpu; 0
+       when disabled.  Bit 1 is reserved and must be zero.  When PV end of
+       interrupt is enabled (bit 0 set), bits 63-2 hold a 4-byte aligned
+       physical address of a 4 byte memory area which must be in guest RAM and
+       must be zeroed.
+
+       The first, least significant bit of 4 byte memory location will be
+       written to by the hypervisor, typically at the time of interrupt
+       injection.  Value of 1 means that guest can skip writing EOI to the apic
+       (using MSR or MMIO write); instead, it is sufficient to signal
+       EOI by clearing the bit in guest memory - this location will
+       later be polled by the hypervisor.
+       Value of 0 means that the EOI write is required.
+
+       It is always safe for the guest to ignore the optimization and perform
+       the APIC EOI write anyway.
+
+       Hypervisor is guaranteed to only modify this least
+       significant bit while in the current VCPU context, this means that
+       guest does not need to use either lock prefix or memory ordering
+       primitives to synchronise with the hypervisor.
+
+       However, hypervisor can set and clear this memory bit at any time:
+       therefore to make sure hypervisor does not interrupt the
+       guest and clear the least significant bit in the memory area
+       in the window between guest testing it to detect
+       whether it can skip EOI apic write and between guest
+       clearing it to signal EOI to the hypervisor,
+       guest must both read the least significant bit in the memory area and
+       clear it using a single CPU instruction, such as test and clear, or
+       compare and exchange.
+
+MSR_KVM_POLL_CONTROL: 0x4b564d05
+       Control host-side polling.
+
+       data: Bit 0 enables (1) or disables (0) host-side HLT polling logic.
+
+       KVM guests can request the host not to poll on HLT, for example if
+       they are performing polling themselves.
+
diff --git a/Documentation/virt/kvm/nested-vmx.txt b/Documentation/virt/kvm/nested-vmx.txt
new file mode 100644 (file)
index 0000000..97eb135
--- /dev/null
@@ -0,0 +1,240 @@
+Nested VMX
+==========
+
+Overview
+---------
+
+On Intel processors, KVM uses Intel's VMX (Virtual-Machine eXtensions)
+to easily and efficiently run guest operating systems. Normally, these guests
+*cannot* themselves be hypervisors running their own guests, because in VMX,
+guests cannot use VMX instructions.
+
+The "Nested VMX" feature adds this missing capability - of running guest
+hypervisors (which use VMX) with their own nested guests. It does so by
+allowing a guest to use VMX instructions, and correctly and efficiently
+emulating them using the single level of VMX available in the hardware.
+
+We describe in much greater detail the theory behind the nested VMX feature,
+its implementation and its performance characteristics, in the OSDI 2010 paper
+"The Turtles Project: Design and Implementation of Nested Virtualization",
+available at:
+
+       http://www.usenix.org/events/osdi10/tech/full_papers/Ben-Yehuda.pdf
+
+
+Terminology
+-----------
+
+Single-level virtualization has two levels - the host (KVM) and the guests.
+In nested virtualization, we have three levels: The host (KVM), which we call
+L0, the guest hypervisor, which we call L1, and its nested guest, which we
+call L2.
+
+
+Running nested VMX
+------------------
+
+The nested VMX feature is disabled by default. It can be enabled by giving
+the "nested=1" option to the kvm-intel module.
+
+No modifications are required to user space (qemu). However, qemu's default
+emulated CPU type (qemu64) does not list the "VMX" CPU feature, so it must be
+explicitly enabled, by giving qemu one of the following options:
+
+     -cpu host              (emulated CPU has all features of the real CPU)
+
+     -cpu qemu64,+vmx       (add just the vmx feature to a named CPU type)
+
+
+ABIs
+----
+
+Nested VMX aims to present a standard and (eventually) fully-functional VMX
+implementation for the a guest hypervisor to use. As such, the official
+specification of the ABI that it provides is Intel's VMX specification,
+namely volume 3B of their "Intel 64 and IA-32 Architectures Software
+Developer's Manual". Not all of VMX's features are currently fully supported,
+but the goal is to eventually support them all, starting with the VMX features
+which are used in practice by popular hypervisors (KVM and others).
+
+As a VMX implementation, nested VMX presents a VMCS structure to L1.
+As mandated by the spec, other than the two fields revision_id and abort,
+this structure is *opaque* to its user, who is not supposed to know or care
+about its internal structure. Rather, the structure is accessed through the
+VMREAD and VMWRITE instructions.
+Still, for debugging purposes, KVM developers might be interested to know the
+internals of this structure; This is struct vmcs12 from arch/x86/kvm/vmx.c.
+
+The name "vmcs12" refers to the VMCS that L1 builds for L2. In the code we
+also have "vmcs01", the VMCS that L0 built for L1, and "vmcs02" is the VMCS
+which L0 builds to actually run L2 - how this is done is explained in the
+aforementioned paper.
+
+For convenience, we repeat the content of struct vmcs12 here. If the internals
+of this structure changes, this can break live migration across KVM versions.
+VMCS12_REVISION (from vmx.c) should be changed if struct vmcs12 or its inner
+struct shadow_vmcs is ever changed.
+
+       typedef u64 natural_width;
+       struct __packed vmcs12 {
+               /* According to the Intel spec, a VMCS region must start with
+                * these two user-visible fields */
+               u32 revision_id;
+               u32 abort;
+
+               u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+               u32 padding[7]; /* room for future expansion */
+
+               u64 io_bitmap_a;
+               u64 io_bitmap_b;
+               u64 msr_bitmap;
+               u64 vm_exit_msr_store_addr;
+               u64 vm_exit_msr_load_addr;
+               u64 vm_entry_msr_load_addr;
+               u64 tsc_offset;
+               u64 virtual_apic_page_addr;
+               u64 apic_access_addr;
+               u64 ept_pointer;
+               u64 guest_physical_address;
+               u64 vmcs_link_pointer;
+               u64 guest_ia32_debugctl;
+               u64 guest_ia32_pat;
+               u64 guest_ia32_efer;
+               u64 guest_pdptr0;
+               u64 guest_pdptr1;
+               u64 guest_pdptr2;
+               u64 guest_pdptr3;
+               u64 host_ia32_pat;
+               u64 host_ia32_efer;
+               u64 padding64[8]; /* room for future expansion */
+               natural_width cr0_guest_host_mask;
+               natural_width cr4_guest_host_mask;
+               natural_width cr0_read_shadow;
+               natural_width cr4_read_shadow;
+               natural_width cr3_target_value0;
+               natural_width cr3_target_value1;
+               natural_width cr3_target_value2;
+               natural_width cr3_target_value3;
+               natural_width exit_qualification;
+               natural_width guest_linear_address;
+               natural_width guest_cr0;
+               natural_width guest_cr3;
+               natural_width guest_cr4;
+               natural_width guest_es_base;
+               natural_width guest_cs_base;
+               natural_width guest_ss_base;
+               natural_width guest_ds_base;
+               natural_width guest_fs_base;
+               natural_width guest_gs_base;
+               natural_width guest_ldtr_base;
+               natural_width guest_tr_base;
+               natural_width guest_gdtr_base;
+               natural_width guest_idtr_base;
+               natural_width guest_dr7;
+               natural_width guest_rsp;
+               natural_width guest_rip;
+               natural_width guest_rflags;
+               natural_width guest_pending_dbg_exceptions;
+               natural_width guest_sysenter_esp;
+               natural_width guest_sysenter_eip;
+               natural_width host_cr0;
+               natural_width host_cr3;
+               natural_width host_cr4;
+               natural_width host_fs_base;
+               natural_width host_gs_base;
+               natural_width host_tr_base;
+               natural_width host_gdtr_base;
+               natural_width host_idtr_base;
+               natural_width host_ia32_sysenter_esp;
+               natural_width host_ia32_sysenter_eip;
+               natural_width host_rsp;
+               natural_width host_rip;
+               natural_width paddingl[8]; /* room for future expansion */
+               u32 pin_based_vm_exec_control;
+               u32 cpu_based_vm_exec_control;
+               u32 exception_bitmap;
+               u32 page_fault_error_code_mask;
+               u32 page_fault_error_code_match;
+               u32 cr3_target_count;
+               u32 vm_exit_controls;
+               u32 vm_exit_msr_store_count;
+               u32 vm_exit_msr_load_count;
+               u32 vm_entry_controls;
+               u32 vm_entry_msr_load_count;
+               u32 vm_entry_intr_info_field;
+               u32 vm_entry_exception_error_code;
+               u32 vm_entry_instruction_len;
+               u32 tpr_threshold;
+               u32 secondary_vm_exec_control;
+               u32 vm_instruction_error;
+               u32 vm_exit_reason;
+               u32 vm_exit_intr_info;
+               u32 vm_exit_intr_error_code;
+               u32 idt_vectoring_info_field;
+               u32 idt_vectoring_error_code;
+               u32 vm_exit_instruction_len;
+               u32 vmx_instruction_info;
+               u32 guest_es_limit;
+               u32 guest_cs_limit;
+               u32 guest_ss_limit;
+               u32 guest_ds_limit;
+               u32 guest_fs_limit;
+               u32 guest_gs_limit;
+               u32 guest_ldtr_limit;
+               u32 guest_tr_limit;
+               u32 guest_gdtr_limit;
+               u32 guest_idtr_limit;
+               u32 guest_es_ar_bytes;
+               u32 guest_cs_ar_bytes;
+               u32 guest_ss_ar_bytes;
+               u32 guest_ds_ar_bytes;
+               u32 guest_fs_ar_bytes;
+               u32 guest_gs_ar_bytes;
+               u32 guest_ldtr_ar_bytes;
+               u32 guest_tr_ar_bytes;
+               u32 guest_interruptibility_info;
+               u32 guest_activity_state;
+               u32 guest_sysenter_cs;
+               u32 host_ia32_sysenter_cs;
+               u32 padding32[8]; /* room for future expansion */
+               u16 virtual_processor_id;
+               u16 guest_es_selector;
+               u16 guest_cs_selector;
+               u16 guest_ss_selector;
+               u16 guest_ds_selector;
+               u16 guest_fs_selector;
+               u16 guest_gs_selector;
+               u16 guest_ldtr_selector;
+               u16 guest_tr_selector;
+               u16 host_es_selector;
+               u16 host_cs_selector;
+               u16 host_ss_selector;
+               u16 host_ds_selector;
+               u16 host_fs_selector;
+               u16 host_gs_selector;
+               u16 host_tr_selector;
+       };
+
+
+Authors
+-------
+
+These patches were written by:
+     Abel Gordon, abelg <at> il.ibm.com
+     Nadav Har'El, nyh <at> il.ibm.com
+     Orit Wasserman, oritw <at> il.ibm.com
+     Ben-Ami Yassor, benami <at> il.ibm.com
+     Muli Ben-Yehuda, muli <at> il.ibm.com
+
+With contributions by:
+     Anthony Liguori, aliguori <at> us.ibm.com
+     Mike Day, mdday <at> us.ibm.com
+     Michael Factor, factor <at> il.ibm.com
+     Zvi Dubitzky, dubi <at> il.ibm.com
+
+And valuable reviews by:
+     Avi Kivity, avi <at> redhat.com
+     Gleb Natapov, gleb <at> redhat.com
+     Marcelo Tosatti, mtosatti <at> redhat.com
+     Kevin Tian, kevin.tian <at> intel.com
+     and others.
diff --git a/Documentation/virt/kvm/ppc-pv.txt b/Documentation/virt/kvm/ppc-pv.txt
new file mode 100644 (file)
index 0000000..e26115c
--- /dev/null
@@ -0,0 +1,212 @@
+The PPC KVM paravirtual interface
+=================================
+
+The basic execution principle by which KVM on PowerPC works is to run all kernel
+space code in PR=1 which is user space. This way we trap all privileged
+instructions and can emulate them accordingly.
+
+Unfortunately that is also the downfall. There are quite some privileged
+instructions that needlessly return us to the hypervisor even though they
+could be handled differently.
+
+This is what the PPC PV interface helps with. It takes privileged instructions
+and transforms them into unprivileged ones with some help from the hypervisor.
+This cuts down virtualization costs by about 50% on some of my benchmarks.
+
+The code for that interface can be found in arch/powerpc/kernel/kvm*
+
+Querying for existence
+======================
+
+To find out if we're running on KVM or not, we leverage the device tree. When
+Linux is running on KVM, a node /hypervisor exists. That node contains a
+compatible property with the value "linux,kvm".
+
+Once you determined you're running under a PV capable KVM, you can now use
+hypercalls as described below.
+
+KVM hypercalls
+==============
+
+Inside the device tree's /hypervisor node there's a property called
+'hypercall-instructions'. This property contains at most 4 opcodes that make
+up the hypercall. To call a hypercall, just call these instructions.
+
+The parameters are as follows:
+
+       Register        IN                      OUT
+
+       r0              -                       volatile
+       r3              1st parameter           Return code
+       r4              2nd parameter           1st output value
+       r5              3rd parameter           2nd output value
+       r6              4th parameter           3rd output value
+       r7              5th parameter           4th output value
+       r8              6th parameter           5th output value
+       r9              7th parameter           6th output value
+       r10             8th parameter           7th output value
+       r11             hypercall number        8th output value
+       r12             -                       volatile
+
+Hypercall definitions are shared in generic code, so the same hypercall numbers
+apply for x86 and powerpc alike with the exception that each KVM hypercall
+also needs to be ORed with the KVM vendor code which is (42 << 16).
+
+Return codes can be as follows:
+
+       Code            Meaning
+
+       0               Success
+       12              Hypercall not implemented
+       <0              Error
+
+The magic page
+==============
+
+To enable communication between the hypervisor and guest there is a new shared
+page that contains parts of supervisor visible register state. The guest can
+map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
+
+With this hypercall issued the guest always gets the magic page mapped at the
+desired location. The first parameter indicates the effective address when the
+MMU is enabled. The second parameter indicates the address in real mode, if
+applicable to the target. For now, we always map the page to -4096. This way we
+can access it using absolute load and store functions. The following
+instruction reads the first field of the magic page:
+
+       ld      rX, -4096(0)
+
+The interface is designed to be extensible should there be need later to add
+additional registers to the magic page. If you add fields to the magic page,
+also define a new hypercall feature to indicate that the host can give you more
+registers. Only if the host supports the additional features, make use of them.
+
+The magic page layout is described by struct kvm_vcpu_arch_shared
+in arch/powerpc/include/asm/kvm_para.h.
+
+Magic page features
+===================
+
+When mapping the magic page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE,
+a second return value is passed to the guest. This second return value contains
+a bitmap of available features inside the magic page.
+
+The following enhancements to the magic page are currently available:
+
+  KVM_MAGIC_FEAT_SR            Maps SR registers r/w in the magic page
+  KVM_MAGIC_FEAT_MAS0_TO_SPRG7 Maps MASn, ESR, PIR and high SPRGs
+
+For enhanced features in the magic page, please check for the existence of the
+feature before using them!
+
+Magic page flags
+================
+
+In addition to features that indicate whether a host is capable of a particular
+feature we also have a channel for a guest to tell the guest whether it's capable
+of something. This is what we call "flags".
+
+Flags are passed to the host in the low 12 bits of the Effective Address.
+
+The following flags are currently available for a guest to expose:
+
+  MAGIC_PAGE_FLAG_NOT_MAPPED_NX Guest handles NX bits correctly wrt magic page
+
+MSR bits
+========
+
+The MSR contains bits that require hypervisor intervention and bits that do
+not require direct hypervisor intervention because they only get interpreted
+when entering the guest or don't have any impact on the hypervisor's behavior.
+
+The following bits are safe to be set inside the guest:
+
+  MSR_EE
+  MSR_RI
+
+If any other bit changes in the MSR, please still use mtmsr(d).
+
+Patched instructions
+====================
+
+The "ld" and "std" instructions are transformed to "lwz" and "stw" instructions
+respectively on 32 bit systems with an added offset of 4 to accommodate for big
+endianness.
+
+The following is a list of mapping the Linux kernel performs when running as
+guest. Implementing any of those mappings is optional, as the instruction traps
+also act on the shared page. So calling privileged instructions still works as
+before.
+
+From                   To
+====                   ==
+
+mfmsr  rX              ld      rX, magic_page->msr
+mfsprg rX, 0           ld      rX, magic_page->sprg0
+mfsprg rX, 1           ld      rX, magic_page->sprg1
+mfsprg rX, 2           ld      rX, magic_page->sprg2
+mfsprg rX, 3           ld      rX, magic_page->sprg3
+mfsrr0 rX              ld      rX, magic_page->srr0
+mfsrr1 rX              ld      rX, magic_page->srr1
+mfdar  rX              ld      rX, magic_page->dar
+mfdsisr        rX              lwz     rX, magic_page->dsisr
+
+mtmsr  rX              std     rX, magic_page->msr
+mtsprg 0, rX           std     rX, magic_page->sprg0
+mtsprg 1, rX           std     rX, magic_page->sprg1
+mtsprg 2, rX           std     rX, magic_page->sprg2
+mtsprg 3, rX           std     rX, magic_page->sprg3
+mtsrr0 rX              std     rX, magic_page->srr0
+mtsrr1 rX              std     rX, magic_page->srr1
+mtdar  rX              std     rX, magic_page->dar
+mtdsisr        rX              stw     rX, magic_page->dsisr
+
+tlbsync                        nop
+
+mtmsrd rX, 0           b       <special mtmsr section>
+mtmsr  rX              b       <special mtmsr section>
+
+mtmsrd rX, 1           b       <special mtmsrd section>
+
+[Book3S only]
+mtsrin rX, rY          b       <special mtsrin section>
+
+[BookE only]
+wrteei [0|1]           b       <special wrteei section>
+
+
+Some instructions require more logic to determine what's going on than a load
+or store instruction can deliver. To enable patching of those, we keep some
+RAM around where we can live translate instructions to. What happens is the
+following:
+
+       1) copy emulation code to memory
+       2) patch that code to fit the emulated instruction
+       3) patch that code to return to the original pc + 4
+       4) patch the original instruction to branch to the new code
+
+That way we can inject an arbitrary amount of code as replacement for a single
+instruction. This allows us to check for pending interrupts when setting EE=1
+for example.
+
+Hypercall ABIs in KVM on PowerPC
+=================================
+1) KVM hypercalls (ePAPR)
+
+These are ePAPR compliant hypercall implementation (mentioned above). Even
+generic hypercalls are implemented here, like the ePAPR idle hcall. These are
+available on all targets.
+
+2) PAPR hypercalls
+
+PAPR hypercalls are needed to run server PowerPC PAPR guests (-M pseries in QEMU).
+These are the same hypercalls that pHyp, the POWER hypervisor implements. Some of
+them are handled in the kernel, some are handled in user space. This is only
+available on book3s_64.
+
+3) OSI hypercalls
+
+Mac-on-Linux is another user of KVM on PowerPC, which has its own hypercall (long
+before KVM). This is supported to maintain compatibility. All these hypercalls get
+forwarded to user space. This is only useful on book3s_32, but can be used with
+book3s_64 as well.
diff --git a/Documentation/virt/kvm/review-checklist.txt b/Documentation/virt/kvm/review-checklist.txt
new file mode 100644 (file)
index 0000000..499af49
--- /dev/null
@@ -0,0 +1,38 @@
+Review checklist for kvm patches
+================================
+
+1.  The patch must follow Documentation/process/coding-style.rst and
+    Documentation/process/submitting-patches.rst.
+
+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/virt/kvm/api.txt
+    - the API must be discoverable using KVM_CHECK_EXTENSION
+
+4.  New state must include support for save/restore.
+
+5.  New features must default to off (userspace should explicitly request them).
+    Performance improvements can and should default to on.
+
+6.  New cpu features should be exposed via KVM_GET_SUPPORTED_CPUID2
+
+7.  Emulator changes should be accompanied by unit tests for qemu-kvm.git
+    kvm/test directory.
+
+8.  Changes should be vendor neutral when possible.  Changes to common code
+    are better than duplicating changes to vendor code.
+
+9.  Similarly, prefer changes to arch independent code than to arch dependent
+    code.
+
+10. User/kernel interfaces and guest/host interfaces must be 64-bit clean
+    (all variables and sizes naturally aligned on 64-bit; use specific types
+    only - u64 rather than ulong).
+
+11. New guest visible features must either be documented in a hardware manual
+    or be accompanied by documentation.
+
+12. Features must be robust against reset and kexec - for example, shared
+    host/guest memory must be unshared to prevent the host from writing to
+    guest memory that the guest has not reserved for this purpose.
diff --git a/Documentation/virt/kvm/s390-diag.txt b/Documentation/virt/kvm/s390-diag.txt
new file mode 100644 (file)
index 0000000..7c52e5f
--- /dev/null
@@ -0,0 +1,83 @@
+The s390 DIAGNOSE call on KVM
+=============================
+
+KVM on s390 supports the DIAGNOSE call for making hypercalls, both for
+native hypercalls and for selected hypercalls found on other s390
+hypervisors.
+
+Note that bits are numbered as by the usual s390 convention (most significant
+bit on the left).
+
+
+General remarks
+---------------
+
+DIAGNOSE calls by the guest cause a mandatory intercept. This implies
+all supported DIAGNOSE calls need to be handled by either KVM or its
+userspace.
+
+All DIAGNOSE calls supported by KVM use the RS-a format:
+
+--------------------------------------
+|  '83'  | R1 | R3 | B2 |     D2     |
+--------------------------------------
+0        8    12   16   20           31
+
+The second-operand address (obtained by the base/displacement calculation)
+is not used to address data. Instead, bits 48-63 of this address specify
+the function code, and bits 0-47 are ignored.
+
+The supported DIAGNOSE function codes vary by the userspace used. For
+DIAGNOSE function codes not specific to KVM, please refer to the
+documentation for the s390 hypervisors defining them.
+
+
+DIAGNOSE function code 'X'500' - KVM virtio functions
+-----------------------------------------------------
+
+If the function code specifies 0x500, various virtio-related functions
+are performed.
+
+General register 1 contains the virtio subfunction code. Supported
+virtio subfunctions depend on KVM's userspace. Generally, userspace
+provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3).
+
+Upon completion of the DIAGNOSE instruction, general register 2 contains
+the function's return code, which is either a return code or a subcode
+specific value.
+
+Subcode 0 - s390-virtio notification and early console printk
+    Handled by userspace.
+
+Subcode 1 - s390-virtio reset
+    Handled by userspace.
+
+Subcode 2 - s390-virtio set status
+    Handled by userspace.
+
+Subcode 3 - virtio-ccw notification
+    Handled by either userspace or KVM (ioeventfd case).
+
+    General register 2 contains a subchannel-identification word denoting
+    the subchannel of the virtio-ccw proxy device to be notified.
+
+    General register 3 contains the number of the virtqueue to be notified.
+
+    General register 4 contains a 64bit identifier for KVM usage (the
+    kvm_io_bus cookie). If general register 4 does not contain a valid
+    identifier, it is ignored.
+
+    After completion of the DIAGNOSE call, general register 2 may contain
+    a 64bit identifier (in the kvm_io_bus cookie case), or a negative
+    error value, if an internal error occurred.
+
+    See also the virtio standard for a discussion of this hypercall.
+
+
+DIAGNOSE function code 'X'501 - KVM breakpoint
+----------------------------------------------
+
+If the function code specifies 0x501, breakpoint functions may be performed.
+This function code is handled by userspace.
+
+This diagnose function code has no subfunctions and uses no parameters.
diff --git a/Documentation/virt/kvm/timekeeping.txt b/Documentation/virt/kvm/timekeeping.txt
new file mode 100644 (file)
index 0000000..76808a1
--- /dev/null
@@ -0,0 +1,612 @@
+
+       Timekeeping Virtualization for X86-Based Architectures
+
+       Zachary Amsden <zamsden@redhat.com>
+       Copyright (c) 2010, Red Hat.  All rights reserved.
+
+1) Overview
+2) Timing Devices
+3) TSC Hardware
+4) Virtualization Problems
+
+=========================================================================
+
+1) Overview
+
+One of the most complicated parts of the X86 platform, and specifically,
+the virtualization of this platform is the plethora of timing devices available
+and the complexity of emulating those devices.  In addition, virtualization of
+time introduces a new set of challenges because it introduces a multiplexed
+division of time beyond the control of the guest CPU.
+
+First, we will describe the various timekeeping hardware available, then
+present some of the problems which arise and solutions available, giving
+specific recommendations for certain classes of KVM guests.
+
+The purpose of this document is to collect data and information relevant to
+timekeeping which may be difficult to find elsewhere, specifically,
+information relevant to KVM and hardware-based virtualization.
+
+=========================================================================
+
+2) Timing Devices
+
+First we discuss the basic hardware devices available.  TSC and the related
+KVM clock are special enough to warrant a full exposition and are described in
+the following section.
+
+2.1) i8254 - PIT
+
+One of the first timer devices available is the programmable interrupt timer,
+or PIT.  The PIT has a fixed frequency 1.193182 MHz base clock and three
+channels which can be programmed to deliver periodic or one-shot interrupts.
+These three channels can be configured in different modes and have individual
+counters.  Channel 1 and 2 were not available for general use in the original
+IBM PC, and historically were connected to control RAM refresh and the PC
+speaker.  Now the PIT is typically integrated as part of an emulated chipset
+and a separate physical PIT is not used.
+
+The PIT uses I/O ports 0x40 - 0x43.  Access to the 16-bit counters is done
+using single or multiple byte access to the I/O ports.  There are 6 modes
+available, but not all modes are available to all timers, as only timer 2
+has a connected gate input, required for modes 1 and 5.  The gate line is
+controlled by port 61h, bit 0, as illustrated in the following diagram.
+
+ --------------             ----------------
+|              |           |                |
+|  1.1932 MHz  |---------->| CLOCK      OUT | ---------> IRQ 0
+|    Clock     |   |       |                |
+ --------------    |    +->| GATE  TIMER 0  |
+                   |        ----------------
+                   |
+                   |        ----------------
+                   |       |                |
+                   |------>| CLOCK      OUT | ---------> 66.3 KHZ DRAM
+                   |       |                |            (aka /dev/null)
+                   |    +->| GATE  TIMER 1  |
+                   |        ----------------
+                   |
+                   |        ----------------
+                   |       |                |
+                   |------>| CLOCK      OUT | ---------> Port 61h, bit 5
+                           |                |      |
+Port 61h, bit 0 ---------->| GATE  TIMER 2  |       \_.----   ____
+                            ----------------         _|    )--|LPF|---Speaker
+                                                    / *----   \___/
+Port 61h, bit 1 -----------------------------------/
+
+The timer modes are now described.
+
+Mode 0: Single Timeout.   This is a one-shot software timeout that counts down
+ when the gate is high (always true for timers 0 and 1).  When the count
+ reaches zero, the output goes high.
+
+Mode 1: Triggered One-shot.  The output is initially set high.  When the gate
+ line is set high, a countdown is initiated (which does not stop if the gate is
+ lowered), during which the output is set low.  When the count reaches zero,
+ the output goes high.
+
+Mode 2: Rate Generator.  The output is initially set high.  When the countdown
+ reaches 1, the output goes low for one count and then returns high.  The value
+ is reloaded and the countdown automatically resumes.  If the gate line goes
+ low, the count is halted.  If the output is low when the gate is lowered, the
+ output automatically goes high (this only affects timer 2).
+
+Mode 3: Square Wave.   This generates a high / low square wave.  The count
+ determines the length of the pulse, which alternates between high and low
+ when zero is reached.  The count only proceeds when gate is high and is
+ automatically reloaded on reaching zero.  The count is decremented twice at
+ each clock to generate a full high / low cycle at the full periodic rate.
+ If the count is even, the clock remains high for N/2 counts and low for N/2
+ counts; if the clock is odd, the clock is high for (N+1)/2 counts and low
+ for (N-1)/2 counts.  Only even values are latched by the counter, so odd
+ values are not observed when reading.  This is the intended mode for timer 2,
+ which generates sine-like tones by low-pass filtering the square wave output.
+
+Mode 4: Software Strobe.  After programming this mode and loading the counter,
+ the output remains high until the counter reaches zero.  Then the output
+ goes low for 1 clock cycle and returns high.  The counter is not reloaded.
+ Counting only occurs when gate is high.
+
+Mode 5: Hardware Strobe.  After programming and loading the counter, the
+ output remains high.  When the gate is raised, a countdown is initiated
+ (which does not stop if the gate is lowered).  When the counter reaches zero,
+ the output goes low for 1 clock cycle and then returns high.  The counter is
+ not reloaded.
+
+In addition to normal binary counting, the PIT supports BCD counting.  The
+command port, 0x43 is used to set the counter and mode for each of the three
+timers.
+
+PIT commands, issued to port 0x43, using the following bit encoding:
+
+Bit 7-4: Command (See table below)
+Bit 3-1: Mode (000 = Mode 0, 101 = Mode 5, 11X = undefined)
+Bit 0  : Binary (0) / BCD (1)
+
+Command table:
+
+0000 - Latch Timer 0 count for port 0x40
+       sample and hold the count to be read in port 0x40;
+       additional commands ignored until counter is read;
+       mode bits ignored.
+
+0001 - Set Timer 0 LSB mode for port 0x40
+       set timer to read LSB only and force MSB to zero;
+       mode bits set timer mode
+
+0010 - Set Timer 0 MSB mode for port 0x40
+       set timer to read MSB only and force LSB to zero;
+       mode bits set timer mode
+
+0011 - Set Timer 0 16-bit mode for port 0x40
+       set timer to read / write LSB first, then MSB;
+       mode bits set timer mode
+
+0100 - Latch Timer 1 count for port 0x41 - as described above
+0101 - Set Timer 1 LSB mode for port 0x41 - as described above
+0110 - Set Timer 1 MSB mode for port 0x41 - as described above
+0111 - Set Timer 1 16-bit mode for port 0x41 - as described above
+
+1000 - Latch Timer 2 count for port 0x42 - as described above
+1001 - Set Timer 2 LSB mode for port 0x42 - as described above
+1010 - Set Timer 2 MSB mode for port 0x42 - as described above
+1011 - Set Timer 2 16-bit mode for port 0x42 as described above
+
+1101 - General counter latch
+       Latch combination of counters into corresponding ports
+       Bit 3 = Counter 2
+       Bit 2 = Counter 1
+       Bit 1 = Counter 0
+       Bit 0 = Unused
+
+1110 - Latch timer status
+       Latch combination of counter mode into corresponding ports
+       Bit 3 = Counter 2
+       Bit 2 = Counter 1
+       Bit 1 = Counter 0
+
+       The output of ports 0x40-0x42 following this command will be:
+
+       Bit 7 = Output pin
+       Bit 6 = Count loaded (0 if timer has expired)
+       Bit 5-4 = Read / Write mode
+           01 = MSB only
+           10 = LSB only
+           11 = LSB / MSB (16-bit)
+       Bit 3-1 = Mode
+       Bit 0 = Binary (0) / BCD mode (1)
+
+2.2) RTC
+
+The second device which was available in the original PC was the MC146818 real
+time clock.  The original device is now obsolete, and usually emulated by the
+system chipset, sometimes by an HPET and some frankenstein IRQ routing.
+
+The RTC is accessed through CMOS variables, which uses an index register to
+control which bytes are read.  Since there is only one index register, read
+of the CMOS and read of the RTC require lock protection (in addition, it is
+dangerous to allow userspace utilities such as hwclock to have direct RTC
+access, as they could corrupt kernel reads and writes of CMOS memory).
+
+The RTC generates an interrupt which is usually routed to IRQ 8.  The interrupt
+can function as a periodic timer, an additional once a day alarm, and can issue
+interrupts after an update of the CMOS registers by the MC146818 is complete.
+The type of interrupt is signalled in the RTC status registers.
+
+The RTC will update the current time fields by battery power even while the
+system is off.  The current time fields should not be read while an update is
+in progress, as indicated in the status register.
+
+The clock uses a 32.768kHz crystal, so bits 6-4 of register A should be
+programmed to a 32kHz divider if the RTC is to count seconds.
+
+This is the RAM map originally used for the RTC/CMOS:
+
+Location    Size    Description
+------------------------------------------
+00h         byte    Current second (BCD)
+01h         byte    Seconds alarm (BCD)
+02h         byte    Current minute (BCD)
+03h         byte    Minutes alarm (BCD)
+04h         byte    Current hour (BCD)
+05h         byte    Hours alarm (BCD)
+06h         byte    Current day of week (BCD)
+07h         byte    Current day of month (BCD)
+08h         byte    Current month (BCD)
+09h         byte    Current year (BCD)
+0Ah         byte    Register A
+                       bit 7   = Update in progress
+                       bit 6-4 = Divider for clock
+                                  000 = 4.194 MHz
+                                  001 = 1.049 MHz
+                                  010 = 32 kHz
+                                  10X = test modes
+                                  110 = reset / disable
+                                  111 = reset / disable
+                       bit 3-0 = Rate selection for periodic interrupt
+                                  000 = periodic timer disabled
+                                  001 = 3.90625 uS
+                                  010 = 7.8125 uS
+                                  011 = .122070 mS
+                                  100 = .244141 mS
+                                     ...
+                                 1101 = 125 mS
+                                 1110 = 250 mS
+                                 1111 = 500 mS
+0Bh         byte    Register B
+                       bit 7   = Run (0) / Halt (1)
+                       bit 6   = Periodic interrupt enable
+                       bit 5   = Alarm interrupt enable
+                       bit 4   = Update-ended interrupt enable
+                       bit 3   = Square wave interrupt enable
+                       bit 2   = BCD calendar (0) / Binary (1)
+                       bit 1   = 12-hour mode (0) / 24-hour mode (1)
+                       bit 0   = 0 (DST off) / 1 (DST enabled)
+OCh         byte    Register C (read only)
+                       bit 7   = interrupt request flag (IRQF)
+                       bit 6   = periodic interrupt flag (PF)
+                       bit 5   = alarm interrupt flag (AF)
+                       bit 4   = update interrupt flag (UF)
+                       bit 3-0 = reserved
+ODh         byte    Register D (read only)
+                       bit 7   = RTC has power
+                       bit 6-0 = reserved
+32h         byte    Current century BCD (*)
+  (*) location vendor specific and now determined from ACPI global tables
+
+2.3) APIC
+
+On Pentium and later processors, an on-board timer is available to each CPU
+as part of the Advanced Programmable Interrupt Controller.  The APIC is
+accessed through memory-mapped registers and provides interrupt service to each
+CPU, used for IPIs and local timer interrupts.
+
+Although in theory the APIC is a safe and stable source for local interrupts,
+in practice, many bugs and glitches have occurred due to the special nature of
+the APIC CPU-local memory-mapped hardware.  Beware that CPU errata may affect
+the use of the APIC and that workarounds may be required.  In addition, some of
+these workarounds pose unique constraints for virtualization - requiring either
+extra overhead incurred from extra reads of memory-mapped I/O or additional
+functionality that may be more computationally expensive to implement.
+
+Since the APIC is documented quite well in the Intel and AMD manuals, we will
+avoid repetition of the detail here.  It should be pointed out that the APIC
+timer is programmed through the LVT (local vector timer) register, is capable
+of one-shot or periodic operation, and is based on the bus clock divided down
+by the programmable divider register.
+
+2.4) HPET
+
+HPET is quite complex, and was originally intended to replace the PIT / RTC
+support of the X86 PC.  It remains to be seen whether that will be the case, as
+the de facto standard of PC hardware is to emulate these older devices.  Some
+systems designated as legacy free may support only the HPET as a hardware timer
+device.
+
+The HPET spec is rather loose and vague, requiring at least 3 hardware timers,
+but allowing implementation freedom to support many more.  It also imposes no
+fixed rate on the timer frequency, but does impose some extremal values on
+frequency, error and slew.
+
+In general, the HPET is recommended as a high precision (compared to PIT /RTC)
+time source which is independent of local variation (as there is only one HPET
+in any given system).  The HPET is also memory-mapped, and its presence is
+indicated through ACPI tables by the BIOS.
+
+Detailed specification of the HPET is beyond the current scope of this
+document, as it is also very well documented elsewhere.
+
+2.5) Offboard Timers
+
+Several cards, both proprietary (watchdog boards) and commonplace (e1000) have
+timing chips built into the cards which may have registers which are accessible
+to kernel or user drivers.  To the author's knowledge, using these to generate
+a clocksource for a Linux or other kernel has not yet been attempted and is in
+general frowned upon as not playing by the agreed rules of the game.  Such a
+timer device would require additional support to be virtualized properly and is
+not considered important at this time as no known operating system does this.
+
+=========================================================================
+
+3) TSC Hardware
+
+The TSC or time stamp counter is relatively simple in theory; it counts
+instruction cycles issued by the processor, which can be used as a measure of
+time.  In practice, due to a number of problems, it is the most complicated
+timekeeping device to use.
+
+The TSC is represented internally as a 64-bit MSR which can be read with the
+RDMSR, RDTSC, or RDTSCP (when available) instructions.  In the past, hardware
+limitations made it possible to write the TSC, but generally on old hardware it
+was only possible to write the low 32-bits of the 64-bit counter, and the upper
+32-bits of the counter were cleared.  Now, however, on Intel processors family
+0Fh, for models 3, 4 and 6, and family 06h, models e and f, this restriction
+has been lifted and all 64-bits are writable.  On AMD systems, the ability to
+write the TSC MSR is not an architectural guarantee.
+
+The TSC is accessible from CPL-0 and conditionally, for CPL > 0 software by
+means of the CR4.TSD bit, which when enabled, disables CPL > 0 TSC access.
+
+Some vendors have implemented an additional instruction, RDTSCP, which returns
+atomically not just the TSC, but an indicator which corresponds to the
+processor number.  This can be used to index into an array of TSC variables to
+determine offset information in SMP systems where TSCs are not synchronized.
+The presence of this instruction must be determined by consulting CPUID feature
+bits.
+
+Both VMX and SVM provide extension fields in the virtualization hardware which
+allows the guest visible TSC to be offset by a constant.  Newer implementations
+promise to allow the TSC to additionally be scaled, but this hardware is not
+yet widely available.
+
+3.1) TSC synchronization
+
+The TSC is a CPU-local clock in most implementations.  This means, on SMP
+platforms, the TSCs of different CPUs may start at different times depending
+on when the CPUs are powered on.  Generally, CPUs on the same die will share
+the same clock, however, this is not always the case.
+
+The BIOS may attempt to resynchronize the TSCs during the poweron process and
+the operating system or other system software may attempt to do this as well.
+Several hardware limitations make the problem worse - if it is not possible to
+write the full 64-bits of the TSC, it may be impossible to match the TSC in
+newly arriving CPUs to that of the rest of the system, resulting in
+unsynchronized TSCs.  This may be done by BIOS or system software, but in
+practice, getting a perfectly synchronized TSC will not be possible unless all
+values are read from the same clock, which generally only is possible on single
+socket systems or those with special hardware support.
+
+3.2) TSC and CPU hotplug
+
+As touched on already, CPUs which arrive later than the boot time of the system
+may not have a TSC value that is synchronized with the rest of the system.
+Either system software, BIOS, or SMM code may actually try to establish the TSC
+to a value matching the rest of the system, but a perfect match is usually not
+a guarantee.  This can have the effect of bringing a system from a state where
+TSC is synchronized back to a state where TSC synchronization flaws, however
+small, may be exposed to the OS and any virtualization environment.
+
+3.3) TSC and multi-socket / NUMA
+
+Multi-socket systems, especially large multi-socket systems are likely to have
+individual clocksources rather than a single, universally distributed clock.
+Since these clocks are driven by different crystals, they will not have
+perfectly matched frequency, and temperature and electrical variations will
+cause the CPU clocks, and thus the TSCs to drift over time.  Depending on the
+exact clock and bus design, the drift may or may not be fixed in absolute
+error, and may accumulate over time.
+
+In addition, very large systems may deliberately slew the clocks of individual
+cores.  This technique, known as spread-spectrum clocking, reduces EMI at the
+clock frequency and harmonics of it, which may be required to pass FCC
+standards for telecommunications and computer equipment.
+
+It is recommended not to trust the TSCs to remain synchronized on NUMA or
+multiple socket systems for these reasons.
+
+3.4) TSC and C-states
+
+C-states, or idling states of the processor, especially C1E and deeper sleep
+states may be problematic for TSC as well.  The TSC may stop advancing in such
+a state, resulting in a TSC which is behind that of other CPUs when execution
+is resumed.  Such CPUs must be detected and flagged by the operating system
+based on CPU and chipset identifications.
+
+The TSC in such a case may be corrected by catching it up to a known external
+clocksource.
+
+3.5) TSC frequency change / P-states
+
+To make things slightly more interesting, some CPUs may change frequency.  They
+may or may not run the TSC at the same rate, and because the frequency change
+may be staggered or slewed, at some points in time, the TSC rate may not be
+known other than falling within a range of values.  In this case, the TSC will
+not be a stable time source, and must be calibrated against a known, stable,
+external clock to be a usable source of time.
+
+Whether the TSC runs at a constant rate or scales with the P-state is model
+dependent and must be determined by inspecting CPUID, chipset or vendor
+specific MSR fields.
+
+In addition, some vendors have known bugs where the P-state is actually
+compensated for properly during normal operation, but when the processor is
+inactive, the P-state may be raised temporarily to service cache misses from
+other processors.  In such cases, the TSC on halted CPUs could advance faster
+than that of non-halted processors.  AMD Turion processors are known to have
+this problem.
+
+3.6) TSC and STPCLK / T-states
+
+External signals given to the processor may also have the effect of stopping
+the TSC.  This is typically done for thermal emergency power control to prevent
+an overheating condition, and typically, there is no way to detect that this
+condition has happened.
+
+3.7) TSC virtualization - VMX
+
+VMX provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
+instructions, which is enough for full virtualization of TSC in any manner.  In
+addition, VMX allows passing through the host TSC plus an additional TSC_OFFSET
+field specified in the VMCS.  Special instructions must be used to read and
+write the VMCS field.
+
+3.8) TSC virtualization - SVM
+
+SVM provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
+instructions, which is enough for full virtualization of TSC in any manner.  In
+addition, SVM allows passing through the host TSC plus an additional offset
+field specified in the SVM control block.
+
+3.9) TSC feature bits in Linux
+
+In summary, there is no way to guarantee the TSC remains in perfect
+synchronization unless it is explicitly guaranteed by the architecture.  Even
+if so, the TSCs in multi-sockets or NUMA systems may still run independently
+despite being locally consistent.
+
+The following feature bits are used by Linux to signal various TSC attributes,
+but they can only be taken to be meaningful for UP or single node systems.
+
+X86_FEATURE_TSC                : The TSC is available in hardware
+X86_FEATURE_RDTSCP             : The RDTSCP instruction is available
+X86_FEATURE_CONSTANT_TSC       : The TSC rate is unchanged with P-states
+X86_FEATURE_NONSTOP_TSC                : The TSC does not stop in C-states
+X86_FEATURE_TSC_RELIABLE       : TSC sync checks are skipped (VMware)
+
+4) Virtualization Problems
+
+Timekeeping is especially problematic for virtualization because a number of
+challenges arise.  The most obvious problem is that time is now shared between
+the host and, potentially, a number of virtual machines.  Thus the virtual
+operating system does not run with 100% usage of the CPU, despite the fact that
+it may very well make that assumption.  It may expect it to remain true to very
+exacting bounds when interrupt sources are disabled, but in reality only its
+virtual interrupt sources are disabled, and the machine may still be preempted
+at any time.  This causes problems as the passage of real time, the injection
+of machine interrupts and the associated clock sources are no longer completely
+synchronized with real time.
+
+This same problem can occur on native hardware to a degree, as SMM mode may
+steal cycles from the naturally on X86 systems when SMM mode is used by the
+BIOS, but not in such an extreme fashion.  However, the fact that SMM mode may
+cause similar problems to virtualization makes it a good justification for
+solving many of these problems on bare metal.
+
+4.1) Interrupt clocking
+
+One of the most immediate problems that occurs with legacy operating systems
+is that the system timekeeping routines are often designed to keep track of
+time by counting periodic interrupts.  These interrupts may come from the PIT
+or the RTC, but the problem is the same: the host virtualization engine may not
+be able to deliver the proper number of interrupts per second, and so guest
+time may fall behind.  This is especially problematic if a high interrupt rate
+is selected, such as 1000 HZ, which is unfortunately the default for many Linux
+guests.
+
+There are three approaches to solving this problem; first, it may be possible
+to simply ignore it.  Guests which have a separate time source for tracking
+'wall clock' or 'real time' may not need any adjustment of their interrupts to
+maintain proper time.  If this is not sufficient, it may be necessary to inject
+additional interrupts into the guest in order to increase the effective
+interrupt rate.  This approach leads to complications in extreme conditions,
+where host load or guest lag is too much to compensate for, and thus another
+solution to the problem has risen: the guest may need to become aware of lost
+ticks and compensate for them internally.  Although promising in theory, the
+implementation of this policy in Linux has been extremely error prone, and a
+number of buggy variants of lost tick compensation are distributed across
+commonly used Linux systems.
+
+Windows uses periodic RTC clocking as a means of keeping time internally, and
+thus requires interrupt slewing to keep proper time.  It does use a low enough
+rate (ed: is it 18.2 Hz?) however that it has not yet been a problem in
+practice.
+
+4.2) TSC sampling and serialization
+
+As the highest precision time source available, the cycle counter of the CPU
+has aroused much interest from developers.  As explained above, this timer has
+many problems unique to its nature as a local, potentially unstable and
+potentially unsynchronized source.  One issue which is not unique to the TSC,
+but is highlighted because of its very precise nature is sampling delay.  By
+definition, the counter, once read is already old.  However, it is also
+possible for the counter to be read ahead of the actual use of the result.
+This is a consequence of the superscalar execution of the instruction stream,
+which may execute instructions out of order.  Such execution is called
+non-serialized.  Forcing serialized execution is necessary for precise
+measurement with the TSC, and requires a serializing instruction, such as CPUID
+or an MSR read.
+
+Since CPUID may actually be virtualized by a trap and emulate mechanism, this
+serialization can pose a performance issue for hardware virtualization.  An
+accurate time stamp counter reading may therefore not always be available, and
+it may be necessary for an implementation to guard against "backwards" reads of
+the TSC as seen from other CPUs, even in an otherwise perfectly synchronized
+system.
+
+4.3) Timespec aliasing
+
+Additionally, this lack of serialization from the TSC poses another challenge
+when using results of the TSC when measured against another time source.  As
+the TSC is much higher precision, many possible values of the TSC may be read
+while another clock is still expressing the same value.
+
+That is, you may read (T,T+10) while external clock C maintains the same value.
+Due to non-serialized reads, you may actually end up with a range which
+fluctuates - from (T-1.. T+10).  Thus, any time calculated from a TSC, but
+calibrated against an external value may have a range of valid values.
+Re-calibrating this computation may actually cause time, as computed after the
+calibration, to go backwards, compared with time computed before the
+calibration.
+
+This problem is particularly pronounced with an internal time source in Linux,
+the kernel time, which is expressed in the theoretically high resolution
+timespec - but which advances in much larger granularity intervals, sometimes
+at the rate of jiffies, and possibly in catchup modes, at a much larger step.
+
+This aliasing requires care in the computation and recalibration of kvmclock
+and any other values derived from TSC computation (such as TSC virtualization
+itself).
+
+4.4) Migration
+
+Migration of a virtual machine raises problems for timekeeping in two ways.
+First, the migration itself may take time, during which interrupts cannot be
+delivered, and after which, the guest time may need to be caught up.  NTP may
+be able to help to some degree here, as the clock correction required is
+typically small enough to fall in the NTP-correctable window.
+
+An additional concern is that timers based off the TSC (or HPET, if the raw bus
+clock is exposed) may now be running at different rates, requiring compensation
+in some way in the hypervisor by virtualizing these timers.  In addition,
+migrating to a faster machine may preclude the use of a passthrough TSC, as a
+faster clock cannot be made visible to a guest without the potential of time
+advancing faster than usual.  A slower clock is less of a problem, as it can
+always be caught up to the original rate.  KVM clock avoids these problems by
+simply storing multipliers and offsets against the TSC for the guest to convert
+back into nanosecond resolution values.
+
+4.5) Scheduling
+
+Since scheduling may be based on precise timing and firing of interrupts, the
+scheduling algorithms of an operating system may be adversely affected by
+virtualization.  In theory, the effect is random and should be universally
+distributed, but in contrived as well as real scenarios (guest device access,
+causes of virtualization exits, possible context switch), this may not always
+be the case.  The effect of this has not been well studied.
+
+In an attempt to work around this, several implementations have provided a
+paravirtualized scheduler clock, which reveals the true amount of CPU time for
+which a virtual machine has been running.
+
+4.6) Watchdogs
+
+Watchdog timers, such as the lock detector in Linux may fire accidentally when
+running under hardware virtualization due to timer interrupts being delayed or
+misinterpretation of the passage of real time.  Usually, these warnings are
+spurious and can be ignored, but in some circumstances it may be necessary to
+disable such detection.
+
+4.7) Delays and precision timing
+
+Precise timing and delays may not be possible in a virtualized system.  This
+can happen if the system is controlling physical hardware, or issues delays to
+compensate for slower I/O to and from devices.  The first issue is not solvable
+in general for a virtualized system; hardware control software can't be
+adequately virtualized without a full real-time operating system, which would
+require an RT aware virtualization platform.
+
+The second issue may cause performance problems, but this is unlikely to be a
+significant issue.  In many cases these delays may be eliminated through
+configuration or paravirtualization.
+
+4.8) Covert channels and leaks
+
+In addition to the above problems, time information will inevitably leak to the
+guest about the host in anything but a perfect implementation of virtualized
+time.  This may allow the guest to infer the presence of a hypervisor (as in a
+red-pill type detection), and it may allow information to leak between guests
+by using CPU utilization itself as a signalling channel.  Preventing such
+problems would require completely isolated virtual time which may not track
+real time any longer.  This may be useful in certain security or QA contexts,
+but in general isn't recommended for real-world deployment scenarios.
diff --git a/Documentation/virt/kvm/vcpu-requests.rst b/Documentation/virt/kvm/vcpu-requests.rst
new file mode 100644 (file)
index 0000000..5feb370
--- /dev/null
@@ -0,0 +1,307 @@
+=================
+KVM VCPU Requests
+=================
+
+Overview
+========
+
+KVM supports an internal API enabling threads to request a VCPU thread to
+perform some activity.  For example, a thread may request a VCPU to flush
+its TLB with a VCPU request.  The API consists of the following functions::
+
+  /* Check if any requests are pending for VCPU @vcpu. */
+  bool kvm_request_pending(struct kvm_vcpu *vcpu);
+
+  /* Check if VCPU @vcpu has request @req pending. */
+  bool kvm_test_request(int req, struct kvm_vcpu *vcpu);
+
+  /* Clear request @req for VCPU @vcpu. */
+  void kvm_clear_request(int req, struct kvm_vcpu *vcpu);
+
+  /*
+   * Check if VCPU @vcpu has request @req pending. When the request is
+   * pending it will be cleared and a memory barrier, which pairs with
+   * another in kvm_make_request(), will be issued.
+   */
+  bool kvm_check_request(int req, struct kvm_vcpu *vcpu);
+
+  /*
+   * Make request @req of VCPU @vcpu. Issues a memory barrier, which pairs
+   * with another in kvm_check_request(), prior to setting the request.
+   */
+  void kvm_make_request(int req, struct kvm_vcpu *vcpu);
+
+  /* Make request @req of all VCPUs of the VM with struct kvm @kvm. */
+  bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
+
+Typically a requester wants the VCPU to perform the activity as soon
+as possible after making the request.  This means most requests
+(kvm_make_request() calls) are followed by a call to kvm_vcpu_kick(),
+and kvm_make_all_cpus_request() has the kicking of all VCPUs built
+into it.
+
+VCPU Kicks
+----------
+
+The goal of a VCPU kick is to bring a VCPU thread out of guest mode in
+order to perform some KVM maintenance.  To do so, an IPI is sent, forcing
+a guest mode exit.  However, a VCPU thread may not be in guest mode at the
+time of the kick.  Therefore, depending on the mode and state of the VCPU
+thread, there are two other actions a kick may take.  All three actions
+are listed below:
+
+1) Send an IPI.  This forces a guest mode exit.
+2) Waking a sleeping VCPU.  Sleeping VCPUs are VCPU threads outside guest
+   mode that wait on waitqueues.  Waking them removes the threads from
+   the waitqueues, allowing the threads to run again.  This behavior
+   may be suppressed, see KVM_REQUEST_NO_WAKEUP below.
+3) Nothing.  When the VCPU is not in guest mode and the VCPU thread is not
+   sleeping, then there is nothing to do.
+
+VCPU Mode
+---------
+
+VCPUs have a mode state, ``vcpu->mode``, that is used to track whether the
+guest is running in guest mode or not, as well as some specific
+outside guest mode states.  The architecture may use ``vcpu->mode`` to
+ensure VCPU requests are seen by VCPUs (see "Ensuring Requests Are Seen"),
+as well as to avoid sending unnecessary IPIs (see "IPI Reduction"), and
+even to ensure IPI acknowledgements are waited upon (see "Waiting for
+Acknowledgements").  The following modes are defined:
+
+OUTSIDE_GUEST_MODE
+
+  The VCPU thread is outside guest mode.
+
+IN_GUEST_MODE
+
+  The VCPU thread is in guest mode.
+
+EXITING_GUEST_MODE
+
+  The VCPU thread is transitioning from IN_GUEST_MODE to
+  OUTSIDE_GUEST_MODE.
+
+READING_SHADOW_PAGE_TABLES
+
+  The VCPU thread is outside guest mode, but it wants the sender of
+  certain VCPU requests, namely KVM_REQ_TLB_FLUSH, to wait until the VCPU
+  thread is done reading the page tables.
+
+VCPU Request Internals
+======================
+
+VCPU requests are simply bit indices of the ``vcpu->requests`` bitmap.
+This means general bitops, like those documented in [atomic-ops]_ could
+also be used, e.g. ::
+
+  clear_bit(KVM_REQ_UNHALT & KVM_REQUEST_MASK, &vcpu->requests);
+
+However, VCPU request users should refrain from doing so, as it would
+break the abstraction.  The first 8 bits are reserved for architecture
+independent requests, all additional bits are available for architecture
+dependent requests.
+
+Architecture Independent Requests
+---------------------------------
+
+KVM_REQ_TLB_FLUSH
+
+  KVM's common MMU notifier may need to flush all of a guest's TLB
+  entries, calling kvm_flush_remote_tlbs() to do so.  Architectures that
+  choose to use the common kvm_flush_remote_tlbs() implementation will
+  need to handle this VCPU request.
+
+KVM_REQ_MMU_RELOAD
+
+  When shadow page tables are used and memory slots are removed it's
+  necessary to inform each VCPU to completely refresh the tables.  This
+  request is used for that.
+
+KVM_REQ_PENDING_TIMER
+
+  This request may be made from a timer handler run on the host on behalf
+  of a VCPU.  It informs the VCPU thread to inject a timer interrupt.
+
+KVM_REQ_UNHALT
+
+  This request may be made from the KVM common function kvm_vcpu_block(),
+  which is used to emulate an instruction that causes a CPU to halt until
+  one of an architectural specific set of events and/or interrupts is
+  received (determined by checking kvm_arch_vcpu_runnable()).  When that
+  event or interrupt arrives kvm_vcpu_block() makes the request.  This is
+  in contrast to when kvm_vcpu_block() returns due to any other reason,
+  such as a pending signal, which does not indicate the VCPU's halt
+  emulation should stop, and therefore does not make the request.
+
+KVM_REQUEST_MASK
+----------------
+
+VCPU requests should be masked by KVM_REQUEST_MASK before using them with
+bitops.  This is because only the lower 8 bits are used to represent the
+request's number.  The upper bits are used as flags.  Currently only two
+flags are defined.
+
+VCPU Request Flags
+------------------
+
+KVM_REQUEST_NO_WAKEUP
+
+  This flag is applied to requests that only need immediate attention
+  from VCPUs running in guest mode.  That is, sleeping VCPUs do not need
+  to be awaken for these requests.  Sleeping VCPUs will handle the
+  requests when they are awaken later for some other reason.
+
+KVM_REQUEST_WAIT
+
+  When requests with this flag are made with kvm_make_all_cpus_request(),
+  then the caller will wait for each VCPU to acknowledge its IPI before
+  proceeding.  This flag only applies to VCPUs that would receive IPIs.
+  If, for example, the VCPU is sleeping, so no IPI is necessary, then
+  the requesting thread does not wait.  This means that this flag may be
+  safely combined with KVM_REQUEST_NO_WAKEUP.  See "Waiting for
+  Acknowledgements" for more information about requests with
+  KVM_REQUEST_WAIT.
+
+VCPU Requests with Associated State
+===================================
+
+Requesters that want the receiving VCPU to handle new state need to ensure
+the newly written state is observable to the receiving VCPU thread's CPU
+by the time it observes the request.  This means a write memory barrier
+must be inserted after writing the new state and before setting the VCPU
+request bit.  Additionally, on the receiving VCPU thread's side, a
+corresponding read barrier must be inserted after reading the request bit
+and before proceeding to read the new state associated with it.  See
+scenario 3, Message and Flag, of [lwn-mb]_ and the kernel documentation
+[memory-barriers]_.
+
+The pair of functions, kvm_check_request() and kvm_make_request(), provide
+the memory barriers, allowing this requirement to be handled internally by
+the API.
+
+Ensuring Requests Are Seen
+==========================
+
+When making requests to VCPUs, we want to avoid the receiving VCPU
+executing in guest mode for an arbitrary long time without handling the
+request.  We can be sure this won't happen as long as we ensure the VCPU
+thread checks kvm_request_pending() before entering guest mode and that a
+kick will send an IPI to force an exit from guest mode when necessary.
+Extra care must be taken to cover the period after the VCPU thread's last
+kvm_request_pending() check and before it has entered guest mode, as kick
+IPIs will only trigger guest mode exits for VCPU threads that are in guest
+mode or at least have already disabled interrupts in order to prepare to
+enter guest mode.  This means that an optimized implementation (see "IPI
+Reduction") must be certain when it's safe to not send the IPI.  One
+solution, which all architectures except s390 apply, is to:
+
+- set ``vcpu->mode`` to IN_GUEST_MODE between disabling the interrupts and
+  the last kvm_request_pending() check;
+- enable interrupts atomically when entering the guest.
+
+This solution also requires memory barriers to be placed carefully in both
+the requesting thread and the receiving VCPU.  With the memory barriers we
+can exclude the possibility of a VCPU thread observing
+!kvm_request_pending() on its last check and then not receiving an IPI for
+the next request made of it, even if the request is made immediately after
+the check.  This is done by way of the Dekker memory barrier pattern
+(scenario 10 of [lwn-mb]_).  As the Dekker pattern requires two variables,
+this solution pairs ``vcpu->mode`` with ``vcpu->requests``.  Substituting
+them into the pattern gives::
+
+  CPU1                                    CPU2
+  =================                       =================
+  local_irq_disable();
+  WRITE_ONCE(vcpu->mode, IN_GUEST_MODE);  kvm_make_request(REQ, vcpu);
+  smp_mb();                               smp_mb();
+  if (kvm_request_pending(vcpu)) {        if (READ_ONCE(vcpu->mode) ==
+                                              IN_GUEST_MODE) {
+      ...abort guest entry...                 ...send IPI...
+  }                                       }
+
+As stated above, the IPI is only useful for VCPU threads in guest mode or
+that have already disabled interrupts.  This is why this specific case of
+the Dekker pattern has been extended to disable interrupts before setting
+``vcpu->mode`` to IN_GUEST_MODE.  WRITE_ONCE() and READ_ONCE() are used to
+pedantically implement the memory barrier pattern, guaranteeing the
+compiler doesn't interfere with ``vcpu->mode``'s carefully planned
+accesses.
+
+IPI Reduction
+-------------
+
+As only one IPI is needed to get a VCPU to check for any/all requests,
+then they may be coalesced.  This is easily done by having the first IPI
+sending kick also change the VCPU mode to something !IN_GUEST_MODE.  The
+transitional state, EXITING_GUEST_MODE, is used for this purpose.
+
+Waiting for Acknowledgements
+----------------------------
+
+Some requests, those with the KVM_REQUEST_WAIT flag set, require IPIs to
+be sent, and the acknowledgements to be waited upon, even when the target
+VCPU threads are in modes other than IN_GUEST_MODE.  For example, one case
+is when a target VCPU thread is in READING_SHADOW_PAGE_TABLES mode, which
+is set after disabling interrupts.  To support these cases, the
+KVM_REQUEST_WAIT flag changes the condition for sending an IPI from
+checking that the VCPU is IN_GUEST_MODE to checking that it is not
+OUTSIDE_GUEST_MODE.
+
+Request-less VCPU Kicks
+-----------------------
+
+As the determination of whether or not to send an IPI depends on the
+two-variable Dekker memory barrier pattern, then it's clear that
+request-less VCPU kicks are almost never correct.  Without the assurance
+that a non-IPI generating kick will still result in an action by the
+receiving VCPU, as the final kvm_request_pending() check does for
+request-accompanying kicks, then the kick may not do anything useful at
+all.  If, for instance, a request-less kick was made to a VCPU that was
+just about to set its mode to IN_GUEST_MODE, meaning no IPI is sent, then
+the VCPU thread may continue its entry without actually having done
+whatever it was the kick was meant to initiate.
+
+One exception is x86's posted interrupt mechanism.  In this case, however,
+even the request-less VCPU kick is coupled with the same
+local_irq_disable() + smp_mb() pattern described above; the ON bit
+(Outstanding Notification) in the posted interrupt descriptor takes the
+role of ``vcpu->requests``.  When sending a posted interrupt, PIR.ON is
+set before reading ``vcpu->mode``; dually, in the VCPU thread,
+vmx_sync_pir_to_irr() reads PIR after setting ``vcpu->mode`` to
+IN_GUEST_MODE.
+
+Additional Considerations
+=========================
+
+Sleeping VCPUs
+--------------
+
+VCPU threads may need to consider requests before and/or after calling
+functions that may put them to sleep, e.g. kvm_vcpu_block().  Whether they
+do or not, and, if they do, which requests need consideration, is
+architecture dependent.  kvm_vcpu_block() calls kvm_arch_vcpu_runnable()
+to check if it should awaken.  One reason to do so is to provide
+architectures a function where requests may be checked if necessary.
+
+Clearing Requests
+-----------------
+
+Generally it only makes sense for the receiving VCPU thread to clear a
+request.  However, in some circumstances, such as when the requesting
+thread and the receiving VCPU thread are executed serially, such as when
+they are the same thread, or when they are using some form of concurrency
+control to temporarily execute synchronously, then it's possible to know
+that the request may be cleared immediately, rather than waiting for the
+receiving VCPU thread to handle the request in VCPU RUN.  The only current
+examples of this are kvm_vcpu_block() calls made by VCPUs to block
+themselves.  A possible side-effect of that call is to make the
+KVM_REQ_UNHALT request, which may then be cleared immediately when the
+VCPU returns from the call.
+
+References
+==========
+
+.. [atomic-ops] Documentation/core-api/atomic_ops.rst
+.. [memory-barriers] Documentation/memory-barriers.txt
+.. [lwn-mb] https://lwn.net/Articles/573436/
diff --git a/Documentation/virt/paravirt_ops.rst b/Documentation/virt/paravirt_ops.rst
new file mode 100644 (file)
index 0000000..6b789d2
--- /dev/null
@@ -0,0 +1,35 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+Paravirt_ops
+============
+
+Linux provides support for different hypervisor virtualization technologies.
+Historically different binary kernels would be required in order to support
+different hypervisors, this restriction was removed with pv_ops.
+Linux pv_ops is a virtualization API which enables support for different
+hypervisors. It allows each hypervisor to override critical operations and
+allows a single kernel binary to run on all supported execution environments
+including native machine -- without any hypervisors.
+
+pv_ops provides a set of function pointers which represent operations
+corresponding to low level critical instructions and high level
+functionalities in various areas. pv-ops allows for optimizations at run
+time by enabling binary patching of the low-ops critical operations
+at boot time.
+
+pv_ops operations are classified into three categories:
+
+- simple indirect call
+   These operations correspond to high level functionality where it is
+   known that the overhead of indirect call isn't very important.
+
+- indirect call which allows optimization with binary patch
+   Usually these operations correspond to low level critical instructions. They
+   are called frequently and are performance critical. The overhead is
+   very important.
+
+- a set of macros for hand written assembly code
+   Hand written assembly codes (.S files) also need paravirtualization
+   because they include sensitive instructions or some of code paths in
+   them are very performance critical.
diff --git a/Documentation/virt/uml/UserModeLinux-HOWTO.txt b/Documentation/virt/uml/UserModeLinux-HOWTO.txt
new file mode 100644 (file)
index 0000000..87b80f5
--- /dev/null
@@ -0,0 +1,4589 @@
+  User Mode Linux HOWTO
+  User Mode Linux Core Team
+  Mon Nov 18 14:16:16 EST 2002
+
+  This document describes the use and abuse of Jeff Dike's User Mode
+  Linux: a port of the Linux kernel as a normal Intel Linux process.
+  ______________________________________________________________________
+
+  Table of Contents
+
+  1. Introduction
+
+     1.1 How is User Mode Linux Different?
+     1.2 Why Would I Want User Mode Linux?
+
+  2. Compiling the kernel and modules
+
+     2.1 Compiling the kernel
+     2.2 Compiling and installing kernel modules
+     2.3 Compiling and installing uml_utilities
+
+  3. Running UML and logging in
+
+     3.1 Running UML
+     3.2 Logging in
+     3.3 Examples
+
+  4. UML on 2G/2G hosts
+
+     4.1 Introduction
+     4.2 The problem
+     4.3 The solution
+
+  5. Setting up serial lines and consoles
+
+     5.1 Specifying the device
+     5.2 Specifying the channel
+     5.3 Examples
+
+  6. Setting up the network
+
+     6.1 General setup
+     6.2 Userspace daemons
+     6.3 Specifying ethernet addresses
+     6.4 UML interface setup
+     6.5 Multicast
+     6.6 TUN/TAP with the uml_net helper
+     6.7 TUN/TAP with a preconfigured tap device
+     6.8 Ethertap
+     6.9 The switch daemon
+     6.10 Slip
+     6.11 Slirp
+     6.12 pcap
+     6.13 Setting up the host yourself
+
+  7. Sharing Filesystems between Virtual Machines
+
+     7.1 A warning
+     7.2 Using layered block devices
+     7.3 Note!
+     7.4 Another warning
+     7.5 uml_moo : Merging a COW file with its backing file
+
+  8. Creating filesystems
+
+     8.1 Create the filesystem file
+     8.2 Assign the file to a UML device
+     8.3 Creating and mounting the filesystem
+
+  9. Host file access
+
+     9.1 Using hostfs
+     9.2 hostfs as the root filesystem
+     9.3 Building hostfs
+
+  10. The Management Console
+     10.1 version
+     10.2 halt and reboot
+     10.3 config
+     10.4 remove
+     10.5 sysrq
+     10.6 help
+     10.7 cad
+     10.8 stop
+     10.9 go
+
+  11. Kernel debugging
+
+     11.1 Starting the kernel under gdb
+     11.2 Examining sleeping processes
+     11.3 Running ddd on UML
+     11.4 Debugging modules
+     11.5 Attaching gdb to the kernel
+     11.6 Using alternate debuggers
+
+  12. Kernel debugging examples
+
+     12.1 The case of the hung fsck
+     12.2 Episode 2: The case of the hung fsck
+
+  13. What to do when UML doesn't work
+
+     13.1 Strange compilation errors when you build from source
+     13.2 (obsolete)
+     13.3 A variety of panics and hangs with /tmp on a reiserfs  filesystem
+     13.4 The compile fails with errors about conflicting types for 'open', 'dup', and 'waitpid'
+     13.5 UML doesn't work when /tmp is an NFS filesystem
+     13.6 UML hangs on boot when compiled with gprof support
+     13.7 syslogd dies with a SIGTERM on startup
+     13.8 TUN/TAP networking doesn't work on a 2.4 host
+     13.9 You can network to the host but not to other machines on the net
+     13.10 I have no root and I want to scream
+     13.11 UML build conflict between ptrace.h and ucontext.h
+     13.12 The UML BogoMips is exactly half the host's BogoMips
+     13.13 When you run UML, it immediately segfaults
+     13.14 xterms appear, then immediately disappear
+     13.15 Any other panic, hang, or strange behavior
+
+  14. Diagnosing Problems
+
+     14.1 Case 1 : Normal kernel panics
+     14.2 Case 2 : Tracing thread panics
+     14.3 Case 3 : Tracing thread panics caused by other threads
+     14.4 Case 4 : Hangs
+
+  15. Thanks
+
+     15.1 Code and Documentation
+     15.2 Flushing out bugs
+     15.3 Buglets and clean-ups
+     15.4 Case Studies
+     15.5 Other contributions
+
+
+  ______________________________________________________________________
+
+  1.  Introduction
+
+  Welcome to User Mode Linux.  It's going to be fun.
+
+
+
+  1.1.  How is User Mode Linux Different?
+
+  Normally, the Linux Kernel talks straight to your hardware (video
+  card, keyboard, hard drives, etc), and any programs which run ask the
+  kernel to operate the hardware, like so:
+
+
+
+         +-----------+-----------+----+
+         | Process 1 | Process 2 | ...|
+         +-----------+-----------+----+
+         |       Linux Kernel         |
+         +----------------------------+
+         |         Hardware           |
+         +----------------------------+
+
+
+
+
+  The User Mode Linux Kernel is different; instead of talking to the
+  hardware, it talks to a `real' Linux kernel (called the `host kernel'
+  from now on), like any other program.  Programs can then run inside
+  User-Mode Linux as if they were running under a normal kernel, like
+  so:
+
+
+
+                     +----------------+
+                     | Process 2 | ...|
+         +-----------+----------------+
+         | Process 1 | User-Mode Linux|
+         +----------------------------+
+         |       Linux Kernel         |
+         +----------------------------+
+         |         Hardware           |
+         +----------------------------+
+
+
+
+
+
+  1.2.  Why Would I Want User Mode Linux?
+
+
+  1. If User Mode Linux crashes, your host kernel is still fine.
+
+  2. You can run a usermode kernel as a non-root user.
+
+  3. You can debug the User Mode Linux like any normal process.
+
+  4. You can run gprof (profiling) and gcov (coverage testing).
+
+  5. You can play with your kernel without breaking things.
+
+  6. You can use it as a sandbox for testing new apps.
+
+  7. You can try new development kernels safely.
+
+  8. You can run different distributions simultaneously.
+
+  9. It's extremely fun.
+
+
+
+
+
+  2.  Compiling the kernel and modules
+
+
+
+
+  2.1.  Compiling the kernel
+
+
+  Compiling the user mode kernel is just like compiling any other
+  kernel.  Let's go through the steps, using 2.4.0-prerelease (current
+  as of this writing) as an example:
+
+
+  1. Download the latest UML patch from
+
+     the download page <http://user-mode-linux.sourceforge.net/
+
+     In this example, the file is uml-patch-2.4.0-prerelease.bz2.
+
+
+  2. Download the matching kernel from your favourite kernel mirror,
+     such as:
+
+     ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2
+     <ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2>
+     .
+
+
+  3. Make a directory and unpack the kernel into it.
+
+
+
+       host%
+       mkdir ~/uml
+
+
+
+
+
+
+       host%
+       cd ~/uml
+
+
+
+
+
+
+       host%
+       tar -xzvf linux-2.4.0-prerelease.tar.bz2
+
+
+
+
+
+
+  4. Apply the patch using
+
+
+
+       host%
+       cd ~/uml/linux
+
+
+
+       host%
+       bzcat uml-patch-2.4.0-prerelease.bz2 | patch -p1
+
+
+
+
+
+
+  5. Run your favorite config; `make xconfig ARCH=um' is the most
+     convenient.  `make config ARCH=um' and 'make menuconfig ARCH=um'
+     will work as well.  The defaults will give you a useful kernel.  If
+     you want to change something, go ahead, it probably won't hurt
+     anything.
+
+
+     Note:  If the host is configured with a 2G/2G address space split
+     rather than the usual 3G/1G split, then the packaged UML binaries
+     will not run.  They will immediately segfault.  See ``UML on 2G/2G
+     hosts''  for the scoop on running UML on your system.
+
+
+
+  6. Finish with `make linux ARCH=um': the result is a file called
+     `linux' in the top directory of your source tree.
+
+  Make sure that you don't build this kernel in /usr/src/linux.  On some
+  distributions, /usr/include/asm is a link into this pool.  The user-
+  mode build changes the other end of that link, and things that include
+  <asm/anything.h> stop compiling.
+
+  The sources are also available from cvs at the project's cvs page,
+  which has directions on getting the sources. You can also browse the
+  CVS pool from there.
+
+  If you get the CVS sources, you will have to check them out into an
+  empty directory. You will then have to copy each file into the
+  corresponding directory in the appropriate kernel pool.
+
+  If you don't have the latest kernel pool, you can get the
+  corresponding user-mode sources with
+
+
+       host% cvs co -r v_2_3_x linux
+
+
+
+
+  where 'x' is the version in your pool. Note that you will not get the
+  bug fixes and enhancements that have gone into subsequent releases.
+
+
+  2.2.  Compiling and installing kernel modules
+
+  UML modules are built in the same way as the native kernel (with the
+  exception of the 'ARCH=um' that you always need for UML):
+
+
+       host% make modules ARCH=um
+
+
+
+
+  Any modules that you want to load into this kernel need to be built in
+  the user-mode pool.  Modules from the native kernel won't work.
+
+  You can install them by using ftp or something to copy them into the
+  virtual machine and dropping them into /lib/modules/`uname -r`.
+
+  You can also get the kernel build process to install them as follows:
+
+  1. with the kernel not booted, mount the root filesystem in the top
+     level of the kernel pool:
+
+
+       host% mount root_fs mnt -o loop
+
+
+
+
+
+
+  2. run
+
+
+       host%
+       make modules_install INSTALL_MOD_PATH=`pwd`/mnt ARCH=um
+
+
+
+
+
+
+  3. unmount the filesystem
+
+
+       host% umount mnt
+
+
+
+
+
+
+  4. boot the kernel on it
+
+
+  When the system is booted, you can use insmod as usual to get the
+  modules into the kernel.  A number of things have been loaded into UML
+  as modules, especially filesystems and network protocols and filters,
+  so most symbols which need to be exported probably already are.
+  However, if you do find symbols that need exporting, let  us
+  <http://user-mode-linux.sourceforge.net/>  know, and
+  they'll be "taken care of".
+
+
+
+  2.3.  Compiling and installing uml_utilities
+
+  Many features of the UML kernel require a user-space helper program,
+  so a uml_utilities package is distributed separately from the kernel
+  patch which provides these helpers. Included within this is:
+
+  o  port-helper - Used by consoles which connect to xterms or ports
+
+  o  tunctl - Configuration tool to create and delete tap devices
+
+  o  uml_net - Setuid binary for automatic tap device configuration
+
+  o  uml_switch - User-space virtual switch required for daemon
+     transport
+
+     The uml_utilities tree is compiled with:
+
+
+       host#
+       make && make install
+
+
+
+
+  Note that UML kernel patches may require a specific version of the
+  uml_utilities distribution. If you don't keep up with the mailing
+  lists, ensure that you have the latest release of uml_utilities if you
+  are experiencing problems with your UML kernel, particularly when
+  dealing with consoles or command-line switches to the helper programs
+
+
+
+
+
+
+
+
+  3.  Running UML and logging in
+
+
+
+  3.1.  Running UML
+
+  It runs on 2.2.15 or later, and all 2.4 kernels.
+
+
+  Booting UML is straightforward.  Simply run 'linux': it will try to
+  mount the file `root_fs' in the current directory.  You do not need to
+  run it as root.  If your root filesystem is not named `root_fs', then
+  you need to put a `ubd0=root_fs_whatever' switch on the linux command
+  line.
+
+
+  You will need a filesystem to boot UML from.  There are a number
+  available for download from  here  <http://user-mode-
+  linux.sourceforge.net/> .  There are also  several tools
+  <http://user-mode-linux.sourceforge.net/>  which can be
+  used to generate UML-compatible filesystem images from media.
+  The kernel will boot up and present you with a login prompt.
+
+
+  Note:  If the host is configured with a 2G/2G address space split
+  rather than the usual 3G/1G split, then the packaged UML binaries will
+  not run.  They will immediately segfault.  See ``UML on 2G/2G hosts''
+  for the scoop on running UML on your system.
+
+
+
+  3.2.  Logging in
+
+
+
+  The prepackaged filesystems have a root account with password 'root'
+  and a user account with password 'user'.  The login banner will
+  generally tell you how to log in.  So, you log in and you will find
+  yourself inside a little virtual machine. Our filesystems have a
+  variety of commands and utilities installed (and it is fairly easy to
+  add more), so you will have a lot of tools with which to poke around
+  the system.
+
+  There are a couple of other ways to log in:
+
+  o  On a virtual console
+
+
+
+     Each virtual console that is configured (i.e. the device exists in
+     /dev and /etc/inittab runs a getty on it) will come up in its own
+     xterm.  If you get tired of the xterms, read ``Setting up serial
+     lines and consoles''  to see how to attach the consoles to
+     something else, like host ptys.
+
+
+
+  o  Over the serial line
+
+
+     In the boot output, find a line that looks like:
+
+
+
+       serial line 0 assigned pty /dev/ptyp1
+
+
+
+
+  Attach your favorite terminal program to the corresponding tty.  I.e.
+  for minicom, the command would be
+
+
+       host% minicom -o -p /dev/ttyp1
+
+
+
+
+
+
+  o  Over the net
+
+
+     If the network is running, then you can telnet to the virtual
+     machine and log in to it.  See ``Setting up the network''  to learn
+     about setting up a virtual network.
+
+  When you're done using it, run halt, and the kernel will bring itself
+  down and the process will exit.
+
+
+  3.3.  Examples
+
+  Here are some examples of UML in action:
+
+  o  A login session <http://user-mode-linux.sourceforge.net/login.html>
+
+  o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
+
+
+
+
+
+
+
+  4.  UML on 2G/2G hosts
+
+
+
+
+  4.1.  Introduction
+
+
+  Most Linux machines are configured so that the kernel occupies the
+  upper 1G (0xc0000000 - 0xffffffff) of the 4G address space and
+  processes use the lower 3G (0x00000000 - 0xbfffffff).  However, some
+  machine are configured with a 2G/2G split, with the kernel occupying
+  the upper 2G (0x80000000 - 0xffffffff) and processes using the lower
+  2G (0x00000000 - 0x7fffffff).
+
+
+
+
+  4.2.  The problem
+
+
+  The prebuilt UML binaries on this site will not run on 2G/2G hosts
+  because UML occupies the upper .5G of the 3G process address space
+  (0xa0000000 - 0xbfffffff).  Obviously, on 2G/2G hosts, this is right
+  in the middle of the kernel address space, so UML won't even load - it
+  will immediately segfault.
+
+
+
+
+  4.3.  The solution
+
+
+  The fix for this is to rebuild UML from source after enabling
+  CONFIG_HOST_2G_2G (under 'General Setup').  This will cause UML to
+  load itself in the top .5G of that smaller process address space,
+  where it will run fine.  See ``Compiling the kernel and modules''  if
+  you need help building UML from source.
+
+
+
+
+
+
+
+
+
+
+  5.  Setting up serial lines and consoles
+
+
+  It is possible to attach UML serial lines and consoles to many types
+  of host I/O channels by specifying them on the command line.
+
+
+  You can attach them to host ptys, ttys, file descriptors, and ports.
+  This allows you to do things like
+
+  o  have a UML console appear on an unused host console,
+
+  o  hook two virtual machines together by having one attach to a pty
+     and having the other attach to the corresponding tty
+
+  o  make a virtual machine accessible from the net by attaching a
+     console to a port on the host.
+
+
+  The general format of the command line option is device=channel.
+
+
+
+  5.1.  Specifying the device
+
+  Devices are specified with "con" or "ssl" (console or serial line,
+  respectively), optionally with a device number if you are talking
+  about a specific device.
+
+
+  Using just "con" or "ssl" describes all of the consoles or serial
+  lines.  If you want to talk about console #3 or serial line #10, they
+  would be "con3" and "ssl10", respectively.
+
+
+  A specific device name will override a less general "con=" or "ssl=".
+  So, for example, you can assign a pty to each of the serial lines
+  except for the first two like this:
+
+
+        ssl=pty ssl0=tty:/dev/tty0 ssl1=tty:/dev/tty1
+
+
+
+
+  The specificity of the device name is all that matters; order on the
+  command line is irrelevant.
+
+
+
+  5.2.  Specifying the channel
+
+  There are a number of different types of channels to attach a UML
+  device to, each with a different way of specifying exactly what to
+  attach to.
+
+  o  pseudo-terminals - device=pty pts terminals - device=pts
+
+
+     This will cause UML to allocate a free host pseudo-terminal for the
+     device.  The terminal that it got will be announced in the boot
+     log.  You access it by attaching a terminal program to the
+     corresponding tty:
+
+  o  screen /dev/pts/n
+
+  o  screen /dev/ttyxx
+
+  o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
+     devices
+
+  o  kermit - start it up, 'open' the device, then 'connect'
+
+
+
+
+
+  o  terminals - device=tty:tty device file
+
+
+     This will make UML attach the device to the specified tty (i.e
+
+
+        con1=tty:/dev/tty3
+
+
+
+
+  will attach UML's console 1 to the host's /dev/tty3).  If the tty that
+  you specify is the slave end of a tty/pty pair, something else must
+  have already opened the corresponding pty in order for this to work.
+
+
+
+
+
+  o  xterms - device=xterm
+
+
+     UML will run an xterm and the device will be attached to it.
+
+
+
+
+
+  o  Port - device=port:port number
+
+
+     This will attach the UML devices to the specified host port.
+     Attaching console 1 to the host's port 9000 would be done like
+     this:
+
+
+        con1=port:9000
+
+
+
+
+  Attaching all the serial lines to that port would be done similarly:
+
+
+        ssl=port:9000
+
+
+
+
+  You access these devices by telnetting to that port.  Each active tel-
+  net session gets a different device.  If there are more telnets to a
+  port than UML devices attached to it, then the extra telnet sessions
+  will block until an existing telnet detaches, or until another device
+  becomes active (i.e. by being activated in /etc/inittab).
+
+  This channel has the advantage that you can both attach multiple UML
+  devices to it and know how to access them without reading the UML boot
+  log.  It is also unique in allowing access to a UML from remote
+  machines without requiring that the UML be networked.  This could be
+  useful in allowing public access to UMLs because they would be
+  accessible from the net, but wouldn't need any kind of network
+  filtering or access control because they would have no network access.
+
+
+  If you attach the main console to a portal, then the UML boot will
+  appear to hang.  In reality, it's waiting for a telnet to connect, at
+  which point the boot will proceed.
+
+
+
+
+
+  o  already-existing file descriptors - device=file descriptor
+
+
+     If you set up a file descriptor on the UML command line, you can
+     attach a UML device to it.  This is most commonly used to put the
+     main console back on stdin and stdout after assigning all the other
+     consoles to something else:
+
+
+        con0=fd:0,fd:1 con=pts
+
+
+
+
+
+
+
+
+  o  Nothing - device=null
+
+
+     This allows the device to be opened, in contrast to 'none', but
+     reads will block, and writes will succeed and the data will be
+     thrown out.
+
+
+
+
+
+  o  None - device=none
+
+
+     This causes the device to disappear.
+
+
+
+  You can also specify different input and output channels for a device
+  by putting a comma between them:
+
+
+        ssl3=tty:/dev/tty2,xterm
+
+
+
+
+  will cause serial line 3 to accept input on the host's /dev/tty2 and
+  display output on an xterm.  That's a silly example - the most common
+  use of this syntax is to reattach the main console to stdin and stdout
+  as shown above.
+
+
+  If you decide to move the main console away from stdin/stdout, the
+  initial boot output will appear in the terminal that you're running
+  UML in.  However, once the console driver has been officially
+  initialized, then the boot output will start appearing wherever you
+  specified that console 0 should be.  That device will receive all
+  subsequent output.
+
+
+
+  5.3.  Examples
+
+  There are a number of interesting things you can do with this
+  capability.
+
+
+  First, this is how you get rid of those bleeding console xterms by
+  attaching them to host ptys:
+
+
+        con=pty con0=fd:0,fd:1
+
+
+
+
+  This will make a UML console take over an unused host virtual console,
+  so that when you switch to it, you will see the UML login prompt
+  rather than the host login prompt:
+
+
+        con1=tty:/dev/tty6
+
+
+
+
+  You can attach two virtual machines together with what amounts to a
+  serial line as follows:
+
+  Run one UML with a serial line attached to a pty -
+
+
+        ssl1=pty
+
+
+
+
+  Look at the boot log to see what pty it got (this example will assume
+  that it got /dev/ptyp1).
+
+  Boot the other UML with a serial line attached to the corresponding
+  tty -
+
+
+        ssl1=tty:/dev/ttyp1
+
+
+
+
+  Log in, make sure that it has no getty on that serial line, attach a
+  terminal program like minicom to it, and you should see the login
+  prompt of the other virtual machine.
+
+
+  6.  Setting up the network
+
+
+
+  This page describes how to set up the various transports and to
+  provide a UML instance with network access to the host, other machines
+  on the local net, and the rest of the net.
+
+
+  As of 2.4.5, UML networking has been completely redone to make it much
+  easier to set up, fix bugs, and add new features.
+
+
+  There is a new helper, uml_net, which does the host setup that
+  requires root privileges.
+
+
+  There are currently five transport types available for a UML virtual
+  machine to exchange packets with other hosts:
+
+  o  ethertap
+
+  o  TUN/TAP
+
+  o  Multicast
+
+  o  a switch daemon
+
+  o  slip
+
+  o  slirp
+
+  o  pcap
+
+     The TUN/TAP, ethertap, slip, and slirp transports allow a UML
+     instance to exchange packets with the host.  They may be directed
+     to the host or the host may just act as a router to provide access
+     to other physical or virtual machines.
+
+
+  The pcap transport is a synthetic read-only interface, using the
+  libpcap binary to collect packets from interfaces on the host and
+  filter them.  This is useful for building preconfigured traffic
+  monitors or sniffers.
+
+
+  The daemon and multicast transports provide a completely virtual
+  network to other virtual machines.  This network is completely
+  disconnected from the physical network unless one of the virtual
+  machines on it is acting as a gateway.
+
+
+  With so many host transports, which one should you use?  Here's when
+  you should use each one:
+
+  o  ethertap - if you want access to the host networking and it is
+     running 2.2
+
+  o  TUN/TAP - if you want access to the host networking and it is
+     running 2.4.  Also, the TUN/TAP transport is able to use a
+     preconfigured device, allowing it to avoid using the setuid uml_net
+     helper, which is a security advantage.
+
+  o  Multicast - if you want a purely virtual network and you don't want
+     to set up anything but the UML
+
+  o  a switch daemon - if you want a purely virtual network and you
+     don't mind running the daemon in order to get somewhat better
+     performance
+
+  o  slip - there is no particular reason to run the slip backend unless
+     ethertap and TUN/TAP are just not available for some reason
+
+  o  slirp - if you don't have root access on the host to setup
+     networking, or if you don't want to allocate an IP to your UML
+
+  o  pcap - not much use for actual network connectivity, but great for
+     monitoring traffic on the host
+
+     Ethertap is available on 2.4 and works fine.  TUN/TAP is preferred
+     to it because it has better performance and ethertap is officially
+     considered obsolete in 2.4.  Also, the root helper only needs to
+     run occasionally for TUN/TAP, rather than handling every packet, as
+     it does with ethertap.  This is a slight security advantage since
+     it provides fewer opportunities for a nasty UML user to somehow
+     exploit the helper's root privileges.
+
+
+  6.1.  General setup
+
+  First, you must have the virtual network enabled in your UML.  If are
+  running a prebuilt kernel from this site, everything is already
+  enabled.  If you build the kernel yourself, under the "Network device
+  support" menu, enable "Network device support", and then the three
+  transports.
+
+
+  The next step is to provide a network device to the virtual machine.
+  This is done by describing it on the kernel command line.
+
+  The general format is
+
+
+       eth <n> = <transport> , <transport args>
+
+
+
+
+  For example, a virtual ethernet device may be attached to a host
+  ethertap device as follows:
+
+
+       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
+
+
+
+
+  This sets up eth0 inside the virtual machine to attach itself to the
+  host /dev/tap0, assigns it an ethernet address, and assigns the host
+  tap0 interface an IP address.
+
+
+
+  Note that the IP address you assign to the host end of the tap device
+  must be different than the IP you assign to the eth device inside UML.
+  If you are short on IPs and don't want to consume two per UML, then
+  you can reuse the host's eth IP address for the host ends of the tap
+  devices.  Internally, the UMLs must still get unique IPs for their eth
+  devices.  You can also give the UMLs non-routable IPs (192.168.x.x or
+  10.x.x.x) and have the host masquerade them.  This will let outgoing
+  connections work, but incoming connections won't without more work,
+  such as port forwarding from the host.
+  Also note that when you configure the host side of an interface, it is
+  only acting as a gateway.  It will respond to pings sent to it
+  locally, but is not useful to do that since it's a host interface.
+  You are not talking to the UML when you ping that interface and get a
+  response.
+
+
+  You can also add devices to a UML and remove them at runtime.  See the
+  ``The Management Console''  page for details.
+
+
+  The sections below describe this in more detail.
+
+
+  Once you've decided how you're going to set up the devices, you boot
+  UML, log in, configure the UML side of the devices, and set up routes
+  to the outside world.  At that point, you will be able to talk to any
+  other machines, physical or virtual, on the net.
+
+
+  If ifconfig inside UML fails and the network refuses to come up, run
+  tell you what went wrong.
+
+
+
+  6.2.  Userspace daemons
+
+  You will likely need the setuid helper, or the switch daemon, or both.
+  They are both installed with the RPM and deb, so if you've installed
+  either, you can skip the rest of this section.
+
+
+  If not, then you need to check them out of CVS, build them, and
+  install them.  The helper is uml_net, in CVS /tools/uml_net, and the
+  daemon is uml_switch, in CVS /tools/uml_router.  They are both built
+  with a plain 'make'.  Both need to be installed in a directory that's
+  in your path - /usr/bin is recommend.  On top of that, uml_net needs
+  to be setuid root.
+
+
+
+  6.3.  Specifying ethernet addresses
+
+  Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
+  allow you to specify hardware addresses for the virtual ethernet
+  devices.  This is generally not necessary.  If you don't have a
+  specific reason to do it, you probably shouldn't.  If one is not
+  specified on the command line, the driver will assign one based on the
+  device IP address.  It will provide the address fe:fd:nn:nn:nn:nn
+  where nn.nn.nn.nn is the device IP address.  This is nearly always
+  sufficient to guarantee a unique hardware address for the device.  A
+  couple of exceptions are:
+
+  o  Another set of virtual ethernet devices are on the same network and
+     they are assigned hardware addresses using a different scheme which
+     may conflict with the UML IP address-based scheme
+
+  o  You aren't going to use the device for IP networking, so you don't
+     assign the device an IP address
+
+     If you let the driver provide the hardware address, you should make
+     sure that the device IP address is known before the interface is
+     brought up.  So, inside UML, this will guarantee that:
+
+
+
+  UML#
+  ifconfig eth0 192.168.0.250 up
+
+
+
+
+  If you decide to assign the hardware address yourself, make sure that
+  the first byte of the address is even.  Addresses with an odd first
+  byte are broadcast addresses, which you don't want assigned to a
+  device.
+
+
+
+  6.4.  UML interface setup
+
+  Once the network devices have been described on the command line, you
+  should boot UML and log in.
+
+
+  The first thing to do is bring the interface up:
+
+
+       UML# ifconfig ethn ip-address up
+
+
+
+
+  You should be able to ping the host at this point.
+
+
+  To reach the rest of the world, you should set a default route to the
+  host:
+
+
+       UML# route add default gw host ip
+
+
+
+
+  Again, with host ip of 192.168.0.4:
+
+
+       UML# route add default gw 192.168.0.4
+
+
+
+
+  This page used to recommend setting a network route to your local net.
+  This is wrong, because it will cause UML to try to figure out hardware
+  addresses of the local machines by arping on the interface to the
+  host.  Since that interface is basically a single strand of ethernet
+  with two nodes on it (UML and the host) and arp requests don't cross
+  networks, they will fail to elicit any responses.  So, what you want
+  is for UML to just blindly throw all packets at the host and let it
+  figure out what to do with them, which is what leaving out the network
+  route and adding the default route does.
+
+
+  Note: If you can't communicate with other hosts on your physical
+  ethernet, it's probably because of a network route that's
+  automatically set up.  If you run 'route -n' and see a route that
+  looks like this:
+
+
+
+
+  Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
+  192.168.0.0     0.0.0.0         255.255.255.0   U     0      0      0   eth0
+
+
+
+
+  with a mask that's not 255.255.255.255, then replace it with a route
+  to your host:
+
+
+       UML#
+       route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0
+
+
+
+
+
+
+       UML#
+       route add -host 192.168.0.4 dev eth0
+
+
+
+
+  This, plus the default route to the host, will allow UML to exchange
+  packets with any machine on your ethernet.
+
+
+
+  6.5.  Multicast
+
+  The simplest way to set up a virtual network between multiple UMLs is
+  to use the mcast transport.  This was written by Harald Welte and is
+  present in UML version 2.4.5-5um and later.  Your system must have
+  multicast enabled in the kernel and there must be a multicast-capable
+  network device on the host.  Normally, this is eth0, but if there is
+  no ethernet card on the host, then you will likely get strange error
+  messages when you bring the device up inside UML.
+
+
+  To use it, run two UMLs with
+
+
+        eth0=mcast
+
+
+
+
+  on their command lines.  Log in, configure the ethernet device in each
+  machine with different IP addresses:
+
+
+       UML1# ifconfig eth0 192.168.0.254
+
+
+
+
+
+
+       UML2# ifconfig eth0 192.168.0.253
+
+
+
+
+  and they should be able to talk to each other.
+
+  The full set of command line options for this transport are
+
+
+
+       ethn=mcast,ethernet address,multicast
+       address,multicast port,ttl
+
+
+
+
+  Harald's original README is here <http://user-mode-linux.source-
+  forge.net/>  and explains these in detail, as well as
+  some other issues.
+
+  There is also a related point-to-point only "ucast" transport.
+  This is useful when your network does not support multicast, and
+  all network connections are simple point to point links.
+
+  The full set of command line options for this transport are
+
+
+       ethn=ucast,ethernet address,remote address,listen port,remote port
+
+
+
+
+  6.6.  TUN/TAP with the uml_net helper
+
+  TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
+  host.  The TUN/TAP backend has been in UML since 2.4.9-3um.
+
+
+  The easiest way to get up and running is to let the setuid uml_net
+  helper do the host setup for you.  This involves insmod-ing the tun.o
+  module if necessary, configuring the device, and setting up IP
+  forwarding, routing, and proxy arp.  If you are new to UML networking,
+  do this first.  If you're concerned about the security implications of
+  the setuid helper, use it to get up and running, then read the next
+  section to see how to have UML use a preconfigured tap device, which
+  avoids the use of uml_net.
+
+
+  If you specify an IP address for the host side of the device, the
+  uml_net helper will do all necessary setup on the host - the only
+  requirement is that TUN/TAP be available, either built in to the host
+  kernel or as the tun.o module.
+
+  The format of the command line switch to attach a device to a TUN/TAP
+  device is
+
+
+       eth <n> =tuntap,,, <IP address>
+
+
+
+
+  For example, this argument will attach the UML's eth0 to the next
+  available tap device and assign an ethernet address to it based on its
+  IP address
+
+
+       eth0=tuntap,,,192.168.0.254
+
+
+
+
+
+
+  Note that the IP address that must be used for the eth device inside
+  UML is fixed by the routing and proxy arp that is set up on the
+  TUN/TAP device on the host.  You can use a different one, but it won't
+  work because reply packets won't reach the UML.  This is a feature.
+  It prevents a nasty UML user from doing things like setting the UML IP
+  to the same as the network's nameserver or mail server.
+
+
+  There are a couple potential problems with running the TUN/TAP
+  transport on a 2.4 host kernel
+
+  o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
+     kernel or use the ethertap transport.
+
+  o  With an upgraded kernel, TUN/TAP may fail with
+
+
+       File descriptor in bad state
+
+
+
+
+  This is due to a header mismatch between the upgraded kernel and the
+  kernel that was originally installed on the machine.  The fix is to
+  make sure that /usr/src/linux points to the headers for the running
+  kernel.
+
+  These were pointed out by Tim Robinson <timro at trkr dot net> in
+  <http://www.geocrawler.com/> name="this uml-
+  user post"> .
+
+
+
+  6.7.  TUN/TAP with a preconfigured tap device
+
+  If you prefer not to have UML use uml_net (which is somewhat
+  insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
+  beforehand.  The setup needs to be done as root, but once that's done,
+  there is no need for root assistance.  Setting up the device is done
+  as follows:
+
+  o  Create the device with tunctl (available from the UML utilities
+     tarball)
+
+
+
+
+       host#  tunctl -u uid
+
+
+
+
+  where uid is the user id or username that UML will be run as.  This
+  will tell you what device was created.
+
+  o  Configure the device IP (change IP addresses and device name to
+     suit)
+
+
+
+
+       host#  ifconfig tap0 192.168.0.254 up
+
+
+
+
+
+  o  Set up routing and arping if desired - this is my recipe, there are
+     other ways of doing the same thing
+
+
+       host#
+       bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
+
+       host#
+       route add -host 192.168.0.253 dev tap0
+
+
+
+
+
+
+       host#
+       bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp'
+
+
+
+
+
+
+       host#
+       arp -Ds 192.168.0.253 eth0 pub
+
+
+
+
+  Note that this must be done every time the host boots - this configu-
+  ration is not stored across host reboots.  So, it's probably a good
+  idea to stick it in an rc file.  An even better idea would be a little
+  utility which reads the information from a config file and sets up
+  devices at boot time.
+
+  o  Rather than using up two IPs and ARPing for one of them, you can
+     also provide direct access to your LAN by the UML by using a
+     bridge.
+
+
+       host#
+       brctl addbr br0
+
+
+
+
+
+
+       host#
+       ifconfig eth0 0.0.0.0 promisc up
+
+
+
+
+
+
+       host#
+       ifconfig tap0 0.0.0.0 promisc up
+
+
+
+
+
+
+       host#
+       ifconfig br0 192.168.0.1 netmask 255.255.255.0 up
+
+
+
+
+
+
+
+  host#
+  brctl stp br0 off
+
+
+
+
+
+
+       host#
+       brctl setfd br0 1
+
+
+
+
+
+
+       host#
+       brctl sethello br0 1
+
+
+
+
+
+
+       host#
+       brctl addif br0 eth0
+
+
+
+
+
+
+       host#
+       brctl addif br0 tap0
+
+
+
+
+  Note that 'br0' should be setup using ifconfig with the existing IP
+  address of eth0, as eth0 no longer has its own IP.
+
+  o
+
+
+     Also, the /dev/net/tun device must be writable by the user running
+     UML in order for the UML to use the device that's been configured
+     for it.  The simplest thing to do is
+
+
+       host#  chmod 666 /dev/net/tun
+
+
+
+
+  Making it world-writable looks bad, but it seems not to be
+  exploitable as a security hole.  However, it does allow anyone to cre-
+  ate useless tap devices (useless because they can't configure them),
+  which is a DOS attack.  A somewhat more secure alternative would to be
+  to create a group containing all the users who have preconfigured tap
+  devices and chgrp /dev/net/tun to that group with mode 664 or 660.
+
+
+  o  Once the device is set up, run UML with 'eth0=tuntap,device name'
+     (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
+     mconsole config command).
+
+  o  Bring the eth device up in UML and you're in business.
+
+     If you don't want that tap device any more, you can make it non-
+     persistent with
+
+
+       host#  tunctl -d tap device
+
+
+
+
+  Finally, tunctl has a -b (for brief mode) switch which causes it to
+  output only the name of the tap device it created.  This makes it
+  suitable for capture by a script:
+
+
+       host#  TAP=`tunctl -u 1000 -b`
+
+
+
+
+
+
+  6.8.  Ethertap
+
+  Ethertap is the general mechanism on 2.2 for userspace processes to
+  exchange packets with the kernel.
+
+
+
+  To use this transport, you need to describe the virtual network device
+  on the UML command line.  The general format for this is
+
+
+       eth <n> =ethertap, <device> , <ethernet address> , <tap IP address>
+
+
+
+
+  So, the previous example
+
+
+       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
+
+
+
+
+  attaches the UML eth0 device to the host /dev/tap0, assigns it the
+  ethernet address fe:fd:0:0:0:1, and assigns the IP address
+  192.168.0.254 to the tap device.
+
+
+
+  The tap device is mandatory, but the others are optional.  If the
+  ethernet address is omitted, one will be assigned to it.
+
+
+  The presence of the tap IP address will cause the helper to run and do
+  whatever host setup is needed to allow the virtual machine to
+  communicate with the outside world.  If you're not sure you know what
+  you're doing, this is the way to go.
+
+
+  If it is absent, then you must configure the tap device and whatever
+  arping and routing you will need on the host.  However, even in this
+  case, the uml_net helper still needs to be in your path and it must be
+  setuid root if you're not running UML as root.  This is because the
+  tap device doesn't support SIGIO, which UML needs in order to use
+  something as a source of input.  So, the helper is used as a
+  convenient asynchronous IO thread.
+
+  If you're using the uml_net helper, you can ignore the following host
+  setup - uml_net will do it for you.  You just need to make sure you
+  have ethertap available, either built in to the host kernel or
+  available as a module.
+
+
+  If you want to set things up yourself, you need to make sure that the
+  appropriate /dev entry exists.  If it doesn't, become root and create
+  it as follows:
+
+
+       mknod /dev/tap <minor>  c 36  <minor>  + 16
+
+
+
+
+  For example, this is how to create /dev/tap0:
+
+
+       mknod /dev/tap0 c 36 0 + 16
+
+
+
+
+  You also need to make sure that the host kernel has ethertap support.
+  If ethertap is enabled as a module, you apparently need to insmod
+  ethertap once for each ethertap device you want to enable.  So,
+
+
+       host#
+       insmod ethertap
+
+
+
+
+  will give you the tap0 interface.  To get the tap1 interface, you need
+  to run
+
+
+       host#
+       insmod ethertap unit=1 -o ethertap1
+
+
+
+
+
+
+
+  6.9.  The switch daemon
+
+  Note: This is the daemon formerly known as uml_router, but which was
+  renamed so the network weenies of the world would stop growling at me.
+
+
+  The switch daemon, uml_switch, provides a mechanism for creating a
+  totally virtual network.  By default, it provides no connection to the
+  host network (but see -tap, below).
+
+
+  The first thing you need to do is run the daemon.  Running it with no
+  arguments will make it listen on a default pair of unix domain
+  sockets.
+
+
+  If you want it to listen on a different pair of sockets, use
+
+
+        -unix control socket data socket
+
+
+
+
+
+  If you want it to act as a hub rather than a switch, use
+
+
+        -hub
+
+
+
+
+
+  If you want the switch to be connected to host networking (allowing
+  the umls to get access to the outside world through the host), use
+
+
+        -tap tap0
+
+
+
+
+
+  Note that the tap device must be preconfigured (see "TUN/TAP with a
+  preconfigured tap device", above).  If you're using a different tap
+  device than tap0, specify that instead of tap0.
+
+
+  uml_switch can be backgrounded as follows
+
+
+       host%
+       uml_switch [ options ] < /dev/null > /dev/null
+
+
+
+
+  The reason it doesn't background by default is that it listens to
+  stdin for EOF.  When it sees that, it exits.
+
+
+  The general format of the kernel command line switch is
+
+
+
+       ethn=daemon,ethernet address,socket
+       type,control socket,data socket
+
+
+
+
+  You can leave off everything except the 'daemon'.  You only need to
+  specify the ethernet address if the one that will be assigned to it
+  isn't acceptable for some reason.  The rest of the arguments describe
+  how to communicate with the daemon.  You should only specify them if
+  you told the daemon to use different sockets than the default.  So, if
+  you ran the daemon with no arguments, running the UML on the same
+  machine with
+       eth0=daemon
+
+
+
+
+  will cause the eth0 driver to attach itself to the daemon correctly.
+
+
+
+  6.10.  Slip
+
+  Slip is another, less general, mechanism for a process to communicate
+  with the host networking.  In contrast to the ethertap interface,
+  which exchanges ethernet frames with the host and can be used to
+  transport any higher-level protocol, it can only be used to transport
+  IP.
+
+
+  The general format of the command line switch is
+
+
+
+       ethn=slip,slip IP
+
+
+
+
+  The slip IP argument is the IP address that will be assigned to the
+  host end of the slip device.  If it is specified, the helper will run
+  and will set up the host so that the virtual machine can reach it and
+  the rest of the network.
+
+
+  There are some oddities with this interface that you should be aware
+  of.  You should only specify one slip device on a given virtual
+  machine, and its name inside UML will be 'umn', not 'eth0' or whatever
+  you specified on the command line.  These problems will be fixed at
+  some point.
+
+
+
+  6.11.  Slirp
+
+  slirp uses an external program, usually /usr/bin/slirp, to provide IP
+  only networking connectivity through the host. This is similar to IP
+  masquerading with a firewall, although the translation is performed in
+  user-space, rather than by the kernel.  As slirp does not set up any
+  interfaces on the host, or changes routing, slirp does not require
+  root access or setuid binaries on the host.
+
+
+  The general format of the command line switch for slirp is:
+
+
+
+       ethn=slirp,ethernet address,slirp path
+
+
+
+
+  The ethernet address is optional, as UML will set up the interface
+  with an ethernet address based upon the initial IP address of the
+  interface.  The slirp path is generally /usr/bin/slirp, although it
+  will depend on distribution.
+
+
+  The slirp program can have a number of options passed to the command
+  line and we can't add them to the UML command line, as they will be
+  parsed incorrectly.  Instead, a wrapper shell script can be written or
+  the options inserted into the  /.slirprc file.  More information on
+  all of the slirp options can be found in its man pages.
+
+
+  The eth0 interface on UML should be set up with the IP 10.2.0.15,
+  although you can use anything as long as it is not used by a network
+  you will be connecting to. The default route on UML should be set to
+  use
+
+
+       UML#
+       route add default dev eth0
+
+
+
+
+  slirp provides a number of useful IP addresses which can be used by
+  UML, such as 10.0.2.3 which is an alias for the DNS server specified
+  in /etc/resolv.conf on the host or the IP given in the 'dns' option
+  for slirp.
+
+
+  Even with a baudrate setting higher than 115200, the slirp connection
+  is limited to 115200. If you need it to go faster, the slirp binary
+  needs to be compiled with FULL_BOLT defined in config.h.
+
+
+
+  6.12.  pcap
+
+  The pcap transport is attached to a UML ethernet device on the command
+  line or with uml_mconsole with the following syntax:
+
+
+
+       ethn=pcap,host interface,filter
+       expression,option1,option2
+
+
+
+
+  The expression and options are optional.
+
+
+  The interface is whatever network device on the host you want to
+  sniff.  The expression is a pcap filter expression, which is also what
+  tcpdump uses, so if you know how to specify tcpdump filters, you will
+  use the same expressions here.  The options are up to two of
+  'promisc', control whether pcap puts the host interface into
+  promiscuous mode. 'optimize' and 'nooptimize' control whether the pcap
+  expression optimizer is used.
+
+
+  Example:
+
+
+
+       eth0=pcap,eth0,tcp
+
+       eth1=pcap,eth0,!tcp
+
+
+
+  will cause the UML eth0 to emit all tcp packets on the host eth0 and
+  the UML eth1 to emit all non-tcp packets on the host eth0.
+
+
+
+  6.13.  Setting up the host yourself
+
+  If you don't specify an address for the host side of the ethertap or
+  slip device, UML won't do any setup on the host.  So this is what is
+  needed to get things working (the examples use a host-side IP of
+  192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
+  own network):
+
+  o  The device needs to be configured with its IP address.  Tap devices
+     are also configured with an mtu of 1484.  Slip devices are
+     configured with a point-to-point address pointing at the UML ip
+     address.
+
+
+       host#  ifconfig tap0 arp mtu 1484 192.168.0.251 up
+
+
+
+
+
+
+       host#
+       ifconfig sl0 192.168.0.251 pointopoint 192.168.0.250 up
+
+
+
+
+
+  o  If a tap device is being set up, a route is set to the UML IP.
+
+
+       UML# route add -host 192.168.0.250 gw 192.168.0.251
+
+
+
+
+
+  o  To allow other hosts on your network to see the virtual machine,
+     proxy arp is set up for it.
+
+
+       host#  arp -Ds 192.168.0.250 eth0 pub
+
+
+
+
+
+  o  Finally, the host is set up to route packets.
+
+
+       host#  echo 1 > /proc/sys/net/ipv4/ip_forward
+
+
+
+
+
+
+
+
+
+
+  7.  Sharing Filesystems between Virtual Machines
+
+
+
+
+  7.1.  A warning
+
+  Don't attempt to share filesystems simply by booting two UMLs from the
+  same file.  That's the same thing as booting two physical machines
+  from a shared disk.  It will result in filesystem corruption.
+
+
+
+  7.2.  Using layered block devices
+
+  The way to share a filesystem between two virtual machines is to use
+  the copy-on-write (COW) layering capability of the ubd block driver.
+  As of 2.4.6-2um, the driver supports layering a read-write private
+  device over a read-only shared device.  A machine's writes are stored
+  in the private device, while reads come from either device - the
+  private one if the requested block is valid in it, the shared one if
+  not.  Using this scheme, the majority of data which is unchanged is
+  shared between an arbitrary number of virtual machines, each of which
+  has a much smaller file containing the changes that it has made.  With
+  a large number of UMLs booting from a large root filesystem, this
+  leads to a huge disk space saving.  It will also help performance,
+  since the host will be able to cache the shared data using a much
+  smaller amount of memory, so UML disk requests will be served from the
+  host's memory rather than its disks.
+
+
+
+
+  To add a copy-on-write layer to an existing block device file, simply
+  add the name of the COW file to the appropriate ubd switch:
+
+
+        ubd0=root_fs_cow,root_fs_debian_22
+
+
+
+
+  where 'root_fs_cow' is the private COW file and 'root_fs_debian_22' is
+  the existing shared filesystem.  The COW file need not exist.  If it
+  doesn't, the driver will create and initialize it.  Once the COW file
+  has been initialized, it can be used on its own on the command line:
+
+
+        ubd0=root_fs_cow
+
+
+
+
+  The name of the backing file is stored in the COW file header, so it
+  would be redundant to continue specifying it on the command line.
+
+
+
+  7.3.  Note!
+
+  When checking the size of the COW file in order to see the gobs of
+  space that you're saving, make sure you use 'ls -ls' to see the actual
+  disk consumption rather than the length of the file.  The COW file is
+  sparse, so the length will be very different from the disk usage.
+  Here is a 'ls -l' of a COW file and backing file from one boot and
+  shutdown:
+       host% ls -l cow.debian debian2.2
+       -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
+       -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
+
+
+
+
+  Doesn't look like much saved space, does it?  Well, here's 'ls -ls':
+
+
+       host% ls -ls cow.debian debian2.2
+          880 -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
+       525832 -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
+
+
+
+
+  Now, you can see that the COW file has less than a meg of disk, rather
+  than 492 meg.
+
+
+
+  7.4.  Another warning
+
+  Once a filesystem is being used as a readonly backing file for a COW
+  file, do not boot directly from it or modify it in any way.  Doing so
+  will invalidate any COW files that are using it.  The mtime and size
+  of the backing file are stored in the COW file header at its creation,
+  and they must continue to match.  If they don't, the driver will
+  refuse to use the COW file.
+
+
+
+
+  If you attempt to evade this restriction by changing either the
+  backing file or the COW header by hand, you will get a corrupted
+  filesystem.
+
+
+
+
+  Among other things, this means that upgrading the distribution in a
+  backing file and expecting that all of the COW files using it will see
+  the upgrade will not work.
+
+
+
+
+  7.5.  uml_moo : Merging a COW file with its backing file
+
+  Depending on how you use UML and COW devices, it may be advisable to
+  merge the changes in the COW file into the backing file every once in
+  a while.
+
+
+
+
+  The utility that does this is uml_moo.  Its usage is
+
+
+       host% uml_moo COW file new backing file
+
+
+
+
+  There's no need to specify the backing file since that information is
+  already in the COW file header.  If you're paranoid, boot the new
+  merged file, and if you're happy with it, move it over the old backing
+  file.
+
+
+
+
+  uml_moo creates a new backing file by default as a safety measure.  It
+  also has a destructive merge option which will merge the COW file
+  directly into its current backing file.  This is really only usable
+  when the backing file only has one COW file associated with it.  If
+  there are multiple COWs associated with a backing file, a -d merge of
+  one of them will invalidate all of the others.  However, it is
+  convenient if you're short of disk space, and it should also be
+  noticeably faster than a non-destructive merge.
+
+
+
+
+  uml_moo is installed with the UML deb and RPM.  If you didn't install
+  UML from one of those packages, you can also get it from the UML
+  utilities <http://user-mode-linux.sourceforge.net/
+  utilities>  tar file in tools/moo.
+
+
+
+
+
+
+
+
+  8.  Creating filesystems
+
+
+  You may want to create and mount new UML filesystems, either because
+  your root filesystem isn't large enough or because you want to use a
+  filesystem other than ext2.
+
+
+  This was written on the occasion of reiserfs being included in the
+  2.4.1 kernel pool, and therefore the 2.4.1 UML, so the examples will
+  talk about reiserfs.  This information is generic, and the examples
+  should be easy to translate to the filesystem of your choice.
+
+
+  8.1.  Create the filesystem file
+
+  dd is your friend.  All you need to do is tell dd to create an empty
+  file of the appropriate size.  I usually make it sparse to save time
+  and to avoid allocating disk space until it's actually used.  For
+  example, the following command will create a sparse 100 meg file full
+  of zeroes.
+
+
+       host%
+       dd if=/dev/zero of=new_filesystem seek=100 count=1 bs=1M
+
+
+
+
+
+
+  8.2.  Assign the file to a UML device
+
+  Add an argument like the following to the UML command line:
+
+  ubd4=new_filesystem
+
+
+
+
+  making sure that you use an unassigned ubd device number.
+
+
+
+  8.3.  Creating and mounting the filesystem
+
+  Make sure that the filesystem is available, either by being built into
+  the kernel, or available as a module, then boot up UML and log in.  If
+  the root filesystem doesn't have the filesystem utilities (mkfs, fsck,
+  etc), then get them into UML by way of the net or hostfs.
+
+
+  Make the new filesystem on the device assigned to the new file:
+
+
+       host#  mkreiserfs /dev/ubd/4
+
+
+       <----------- MKREISERFSv2 ----------->
+
+       ReiserFS version 3.6.25
+       Block size 4096 bytes
+       Block count 25856
+       Used blocks 8212
+               Journal - 8192 blocks (18-8209), journal header is in block 8210
+               Bitmaps: 17
+               Root block 8211
+       Hash function "r5"
+       ATTENTION: ALL DATA WILL BE LOST ON '/dev/ubd/4'! (y/n)y
+       journal size 8192 (from 18)
+       Initializing journal - 0%....20%....40%....60%....80%....100%
+       Syncing..done.
+
+
+
+
+  Now, mount it:
+
+
+       UML#
+       mount /dev/ubd/4 /mnt
+
+
+
+
+  and you're in business.
+
+
+
+
+
+
+
+
+
+  9.  Host file access
+
+
+  If you want to access files on the host machine from inside UML, you
+  can treat it as a separate machine and either nfs mount directories
+  from the host or copy files into the virtual machine with scp or rcp.
+  However, since UML is running on the host, it can access those
+  files just like any other process and make them available inside the
+  virtual machine without needing to use the network.
+
+
+  This is now possible with the hostfs virtual filesystem.  With it, you
+  can mount a host directory into the UML filesystem and access the
+  files contained in it just as you would on the host.
+
+
+  9.1.  Using hostfs
+
+  To begin with, make sure that hostfs is available inside the virtual
+  machine with
+
+
+       UML# cat /proc/filesystems
+
+
+
+  .  hostfs should be listed.  If it's not, either rebuild the kernel
+  with hostfs configured into it or make sure that hostfs is built as a
+  module and available inside the virtual machine, and insmod it.
+
+
+  Now all you need to do is run mount:
+
+
+       UML# mount none /mnt/host -t hostfs
+
+
+
+
+  will mount the host's / on the virtual machine's /mnt/host.
+
+
+  If you don't want to mount the host root directory, then you can
+  specify a subdirectory to mount with the -o switch to mount:
+
+
+       UML# mount none /mnt/home -t hostfs -o /home
+
+
+
+
+  will mount the hosts's /home on the virtual machine's /mnt/home.
+
+
+
+  9.2.  hostfs as the root filesystem
+
+  It's possible to boot from a directory hierarchy on the host using
+  hostfs rather than using the standard filesystem in a file.
+
+  To start, you need that hierarchy.  The easiest way is to loop mount
+  an existing root_fs file:
+
+
+       host#  mount root_fs uml_root_dir -o loop
+
+
+
+
+  You need to change the filesystem type of / in etc/fstab to be
+  'hostfs', so that line looks like this:
+
+  /dev/ubd/0       /        hostfs      defaults          1   1
+
+
+
+
+  Then you need to chown to yourself all the files in that directory
+  that are owned by root.  This worked for me:
+
+
+       host#  find . -uid 0 -exec chown jdike {} \;
+
+
+
+
+  Next, make sure that your UML kernel has hostfs compiled in, not as a
+  module.  Then run UML with the boot device pointing at that directory:
+
+
+        ubd0=/path/to/uml/root/directory
+
+
+
+
+  UML should then boot as it does normally.
+
+
+  9.3.  Building hostfs
+
+  If you need to build hostfs because it's not in your kernel, you have
+  two choices:
+
+
+
+  o  Compiling hostfs into the kernel:
+
+
+     Reconfigure the kernel and set the 'Host filesystem' option under
+
+
+  o  Compiling hostfs as a module:
+
+
+     Reconfigure the kernel and set the 'Host filesystem' option under
+     be in arch/um/fs/hostfs/hostfs.o.  Install that in
+     /lib/modules/`uname -r`/fs in the virtual machine, boot it up, and
+
+
+       UML# insmod hostfs
+
+
+
+
+
+
+
+
+
+
+
+
+  10.  The Management Console
+
+
+
+  The UML management console is a low-level interface to the kernel,
+  somewhat like the i386 SysRq interface.  Since there is a full-blown
+  operating system under UML, there is much greater flexibility possible
+  than with the SysRq mechanism.
+
+
+  There are a number of things you can do with the mconsole interface:
+
+  o  get the kernel version
+
+  o  add and remove devices
+
+  o  halt or reboot the machine
+
+  o  Send SysRq commands
+
+  o  Pause and resume the UML
+
+
+  You need the mconsole client (uml_mconsole) which is present in CVS
+  (/tools/mconsole) in 2.4.5-9um and later, and will be in the RPM in
+  2.4.6.
+
+
+  You also need CONFIG_MCONSOLE (under 'General Setup') enabled in UML.
+  When you boot UML, you'll see a line like:
+
+
+       mconsole initialized on /home/jdike/.uml/umlNJ32yL/mconsole
+
+
+
+
+  If you specify a unique machine id one the UML command line, i.e.
+
+
+        umid=debian
+
+
+
+
+  you'll see this
+
+
+       mconsole initialized on /home/jdike/.uml/debian/mconsole
+
+
+
+
+  That file is the socket that uml_mconsole will use to communicate with
+  UML.  Run it with either the umid or the full path as its argument:
+
+
+       host% uml_mconsole debian
+
+
+
+
+  or
+
+
+       host% uml_mconsole /home/jdike/.uml/debian/mconsole
+
+
+
+
+  You'll get a prompt, at which you can run one of these commands:
+
+  o  version
+
+  o  halt
+
+  o  reboot
+
+  o  config
+
+  o  remove
+
+  o  sysrq
+
+  o  help
+
+  o  cad
+
+  o  stop
+
+  o  go
+
+
+  10.1.  version
+
+  This takes no arguments.  It prints the UML version.
+
+
+       (mconsole)  version
+       OK Linux usermode 2.4.5-9um #1 Wed Jun 20 22:47:08 EDT 2001 i686
+
+
+
+
+  There are a couple actual uses for this.  It's a simple no-op which
+  can be used to check that a UML is running.  It's also a way of
+  sending an interrupt to the UML.  This is sometimes useful on SMP
+  hosts, where there's a bug which causes signals to UML to be lost,
+  often causing it to appear to hang.  Sending such a UML the mconsole
+  version command is a good way to 'wake it up' before networking has
+  been enabled, as it does not do anything to the function of the UML.
+
+
+
+  10.2.  halt and reboot
+
+  These take no arguments.  They shut the machine down immediately, with
+  no syncing of disks and no clean shutdown of userspace.  So, they are
+  pretty close to crashing the machine.
+
+
+       (mconsole)  halt
+       OK
+
+
+
+
+
+
+  10.3.  config
+
+  "config" adds a new device to the virtual machine.  Currently the ubd
+  and network drivers support this.  It takes one argument, which is the
+  device to add, with the same syntax as the kernel command line.
+
+
+
+
+  (mconsole)
+  config ubd3=/home/jdike/incoming/roots/root_fs_debian22
+
+  OK
+  (mconsole)  config eth1=mcast
+  OK
+
+
+
+
+
+
+  10.4.  remove
+
+  "remove" deletes a device from the system.  Its argument is just the
+  name of the device to be removed. The device must be idle in whatever
+  sense the driver considers necessary.  In the case of the ubd driver,
+  the removed block device must not be mounted, swapped on, or otherwise
+  open, and in the case of the network driver, the device must be down.
+
+
+       (mconsole)  remove ubd3
+       OK
+       (mconsole)  remove eth1
+       OK
+
+
+
+
+
+
+  10.5.  sysrq
+
+  This takes one argument, which is a single letter.  It calls the
+  generic kernel's SysRq driver, which does whatever is called for by
+  that argument.  See the SysRq documentation in
+  Documentation/admin-guide/sysrq.rst in your favorite kernel tree to
+  see what letters are valid and what they do.
+
+
+
+  10.6.  help
+
+  "help" returns a string listing the valid commands and what each one
+  does.
+
+
+
+  10.7.  cad
+
+  This invokes the Ctl-Alt-Del action on init.  What exactly this ends
+  up doing is up to /etc/inittab.  Normally, it reboots the machine.
+  With UML, this is usually not desired, so if a halt would be better,
+  then find the section of inittab that looks like this
+
+
+       # What to do when CTRL-ALT-DEL is pressed.
+       ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
+
+
+
+
+  and change the command to halt.
+
+
+
+  10.8.  stop
+
+  This puts the UML in a loop reading mconsole requests until a 'go'
+  mconsole command is received. This is very useful for making backups
+  of UML filesystems, as the UML can be stopped, then synced via 'sysrq
+  s', so that everything is written to the filesystem. You can then copy
+  the filesystem and then send the UML 'go' via mconsole.
+
+
+  Note that a UML running with more than one CPU will have problems
+  after you send the 'stop' command, as only one CPU will be held in a
+  mconsole loop and all others will continue as normal.  This is a bug,
+  and will be fixed.
+
+
+
+  10.9.  go
+
+  This resumes a UML after being paused by a 'stop' command. Note that
+  when the UML has resumed, TCP connections may have timed out and if
+  the UML is paused for a long period of time, crond might go a little
+  crazy, running all the jobs it didn't do earlier.
+
+
+
+
+
+
+
+
+  11.  Kernel debugging
+
+
+  Note: The interface that makes debugging, as described here, possible
+  is present in 2.4.0-test6 kernels and later.
+
+
+  Since the user-mode kernel runs as a normal Linux process, it is
+  possible to debug it with gdb almost like any other process.  It is
+  slightly different because the kernel's threads are already being
+  ptraced for system call interception, so gdb can't ptrace them.
+  However, a mechanism has been added to work around that problem.
+
+
+  In order to debug the kernel, you need build it from source.  See
+  ``Compiling the kernel and modules''  for information on doing that.
+  Make sure that you enable CONFIG_DEBUGSYM and CONFIG_PT_PROXY during
+  the config.  These will compile the kernel with -g, and enable the
+  ptrace proxy so that gdb works with UML, respectively.
+
+
+
+
+  11.1.  Starting the kernel under gdb
+
+  You can have the kernel running under the control of gdb from the
+  beginning by putting 'debug' on the command line.  You will get an
+  xterm with gdb running inside it.  The kernel will send some commands
+  to gdb which will leave it stopped at the beginning of start_kernel.
+  At this point, you can get things going with 'next', 'step', or
+  'cont'.
+
+
+  There is a transcript of a debugging session  here <debug-
+  session.html> , with breakpoints being set in the scheduler and in an
+  interrupt handler.
+  11.2.  Examining sleeping processes
+
+  Not every bug is evident in the currently running process.  Sometimes,
+  processes hang in the kernel when they shouldn't because they've
+  deadlocked on a semaphore or something similar.  In this case, when
+  you ^C gdb and get a backtrace, you will see the idle thread, which
+  isn't very relevant.
+
+
+  What you want is the stack of whatever process is sleeping when it
+  shouldn't be.  You need to figure out which process that is, which is
+  generally fairly easy.  Then you need to get its host process id,
+  which you can do either by looking at ps on the host or at
+  task.thread.extern_pid in gdb.
+
+
+  Now what you do is this:
+
+  o  detach from the current thread
+
+
+       (UML gdb)  det
+
+
+
+
+
+  o  attach to the thread you are interested in
+
+
+       (UML gdb)  att <host pid>
+
+
+
+
+
+  o  look at its stack and anything else of interest
+
+
+       (UML gdb)  bt
+
+
+
+
+  Note that you can't do anything at this point that requires that a
+  process execute, e.g. calling a function
+
+  o  when you're done looking at that process, reattach to the current
+     thread and continue it
+
+
+       (UML gdb)
+       att 1
+
+
+
+
+
+
+       (UML gdb)
+       c
+
+
+
+
+  Here, specifying any pid which is not the process id of a UML thread
+  will cause gdb to reattach to the current thread.  I commonly use 1,
+  but any other invalid pid would work.
+
+
+
+  11.3.  Running ddd on UML
+
+  ddd works on UML, but requires a special kludge.  The process goes
+  like this:
+
+  o  Start ddd
+
+
+       host% ddd linux
+
+
+
+
+
+  o  With ps, get the pid of the gdb that ddd started.  You can ask the
+     gdb to tell you, but for some reason that confuses things and
+     causes a hang.
+
+  o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
+     - it will just sit there after you hit return
+
+  o  type 'att 1' to the ddd gdb and you will see something like
+
+
+       0xa013dc51 in __kill ()
+
+
+       (gdb)
+
+
+
+
+
+  o  At this point, type 'c', UML will boot up, and you can use ddd just
+     as you do on any other process.
+
+
+
+  11.4.  Debugging modules
+
+  gdb has support for debugging code which is dynamically loaded into
+  the process.  This support is what is needed to debug kernel modules
+  under UML.
+
+
+  Using that support is somewhat complicated.  You have to tell gdb what
+  object file you just loaded into UML and where in memory it is.  Then,
+  it can read the symbol table, and figure out where all the symbols are
+  from the load address that you provided.  It gets more interesting
+  when you load the module again (i.e. after an rmmod).  You have to
+  tell gdb to forget about all its symbols, including the main UML ones
+  for some reason, then load then all back in again.
+
+
+  There's an easy way and a hard way to do this.  The easy way is to use
+  the umlgdb expect script written by Chandan Kudige.  It basically
+  automates the process for you.
+
+
+  First, you must tell it where your modules are.  There is a list in
+  the script that looks like this:
+       set MODULE_PATHS {
+       "fat" "/usr/src/uml/linux-2.4.18/fs/fat/fat.o"
+       "isofs" "/usr/src/uml/linux-2.4.18/fs/isofs/isofs.o"
+       "minix" "/usr/src/uml/linux-2.4.18/fs/minix/minix.o"
+       }
+
+
+
+
+  You change that to list the names and paths of the modules that you
+  are going to debug.  Then you run it from the toplevel directory of
+  your UML pool and it basically tells you what to do:
+
+
+
+
+                   ******** GDB pid is 21903 ********
+       Start UML as: ./linux <kernel switches> debug gdb-pid=21903
+
+
+
+       GNU gdb 5.0rh-5 Red Hat Linux 7.1
+       Copyright 2001 Free Software Foundation, Inc.
+       GDB is free software, covered by the GNU General Public License, and you are
+       welcome to change it and/or distribute copies of it under certain conditions.
+       Type "show copying" to see the conditions.
+       There is absolutely no warranty for GDB.  Type "show warranty" for details.
+       This GDB was configured as "i386-redhat-linux"...
+       (gdb) b sys_init_module
+       Breakpoint 1 at 0xa0011923: file module.c, line 349.
+       (gdb) att 1
+
+
+
+
+  After you run UML and it sits there doing nothing, you hit return at
+  the 'att 1' and continue it:
+
+
+       Attaching to program: /home/jdike/linux/2.4/um/./linux, process 1
+       0xa00f4221 in __kill ()
+       (UML gdb)  c
+       Continuing.
+
+
+
+
+  At this point, you debug normally.  When you insmod something, the
+  expect magic will kick in and you'll see something like:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+   *** Module hostfs loaded ***
+  Breakpoint 1, sys_init_module (name_user=0x805abb0 "hostfs",
+      mod_user=0x8070e00) at module.c:349
+  349             char *name, *n_name, *name_tmp = NULL;
+  (UML gdb)  finish
+  Run till exit from #0  sys_init_module (name_user=0x805abb0 "hostfs",
+      mod_user=0x8070e00) at module.c:349
+  0xa00e2e23 in execute_syscall (r=0xa8140284) at syscall_kern.c:411
+  411             else res = EXECUTE_SYSCALL(syscall, regs);
+  Value returned is $1 = 0
+  (UML gdb)
+  p/x (int)module_list + module_list->size_of_struct
+
+  $2 = 0xa9021054
+  (UML gdb)  symbol-file ./linux
+  Load new symbol table from "./linux"? (y or n) y
+  Reading symbols from ./linux...
+  done.
+  (UML gdb)
+  add-symbol-file /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o 0xa9021054
+
+  add symbol table from file "/home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o" at
+          .text_addr = 0xa9021054
+   (y or n) y
+
+  Reading symbols from /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o...
+  done.
+  (UML gdb)  p *module_list
+  $1 = {size_of_struct = 84, next = 0xa0178720, name = 0xa9022de0 "hostfs",
+    size = 9016, uc = {usecount = {counter = 0}, pad = 0}, flags = 1,
+    nsyms = 57, ndeps = 0, syms = 0xa9023170, deps = 0x0, refs = 0x0,
+    init = 0xa90221f0 <init_hostfs>, cleanup = 0xa902222c <exit_hostfs>,
+    ex_table_start = 0x0, ex_table_end = 0x0, persist_start = 0x0,
+    persist_end = 0x0, can_unload = 0, runsize = 0, kallsyms_start = 0x0,
+    kallsyms_end = 0x0,
+    archdata_start = 0x1b855 <Address 0x1b855 out of bounds>,
+    archdata_end = 0xe5890000 <Address 0xe5890000 out of bounds>,
+    kernel_data = 0xf689c35d <Address 0xf689c35d out of bounds>}
+  >> Finished loading symbols for hostfs ...
+
+
+
+
+  That's the easy way.  It's highly recommended.  The hard way is
+  described below in case you're interested in what's going on.
+
+
+  Boot the kernel under the debugger and load the module with insmod or
+  modprobe.  With gdb, do:
+
+
+       (UML gdb)  p module_list
+
+
+
+
+  This is a list of modules that have been loaded into the kernel, with
+  the most recently loaded module first.  Normally, the module you want
+  is at module_list.  If it's not, walk down the next links, looking at
+  the name fields until find the module you want to debug.  Take the
+  address of that structure, and add module.size_of_struct (which in
+  2.4.10 kernels is 96 (0x60)) to it.  Gdb can make this hard addition
+  for you :-):
+
+
+
+  (UML gdb)
+  printf "%#x\n", (int)module_list module_list->size_of_struct
+
+
+
+
+  The offset from the module start occasionally changes (before 2.4.0,
+  it was module.size_of_struct + 4), so it's a good idea to check the
+  init and cleanup addresses once in a while, as describe below.  Now
+  do:
+
+
+       (UML gdb)
+       add-symbol-file /path/to/module/on/host that_address
+
+
+
+
+  Tell gdb you really want to do it, and you're in business.
+
+
+  If there's any doubt that you got the offset right, like breakpoints
+  appear not to work, or they're appearing in the wrong place, you can
+  check it by looking at the module structure.  The init and cleanup
+  fields should look like:
+
+
+       init = 0x588066b0 <init_hostfs>, cleanup = 0x588066c0 <exit_hostfs>
+
+
+
+
+  with no offsets on the symbol names.  If the names are right, but they
+  are offset, then the offset tells you how much you need to add to the
+  address you gave to add-symbol-file.
+
+
+  When you want to load in a new version of the module, you need to get
+  gdb to forget about the old one.  The only way I've found to do that
+  is to tell gdb to forget about all symbols that it knows about:
+
+
+       (UML gdb)  symbol-file
+
+
+
+
+  Then reload the symbols from the kernel binary:
+
+
+       (UML gdb)  symbol-file /path/to/kernel
+
+
+
+
+  and repeat the process above.  You'll also need to re-enable break-
+  points.  They were disabled when you dumped all the symbols because
+  gdb couldn't figure out where they should go.
+
+
+
+  11.5.  Attaching gdb to the kernel
+
+  If you don't have the kernel running under gdb, you can attach gdb to
+  it later by sending the tracing thread a SIGUSR1.  The first line of
+  the console output identifies its pid:
+       tracing thread pid = 20093
+
+
+
+
+  When you send it the signal:
+
+
+       host% kill -USR1 20093
+
+
+
+
+  you will get an xterm with gdb running in it.
+
+
+  If you have the mconsole compiled into UML, then the mconsole client
+  can be used to start gdb:
+
+
+       (mconsole)  (mconsole) config gdb=xterm
+
+
+
+
+  will fire up an xterm with gdb running in it.
+
+
+
+  11.6.  Using alternate debuggers
+
+  UML has support for attaching to an already running debugger rather
+  than starting gdb itself.  This is present in CVS as of 17 Apr 2001.
+  I sent it to Alan for inclusion in the ac tree, and it will be in my
+  2.4.4 release.
+
+
+  This is useful when gdb is a subprocess of some UI, such as emacs or
+  ddd.  It can also be used to run debuggers other than gdb on UML.
+  Below is an example of using strace as an alternate debugger.
+
+
+  To do this, you need to get the pid of the debugger and pass it in
+  with the
+
+
+  If you are using gdb under some UI, then tell it to 'att 1', and
+  you'll find yourself attached to UML.
+
+
+  If you are using something other than gdb as your debugger, then
+  you'll need to get it to do the equivalent of 'att 1' if it doesn't do
+  it automatically.
+
+
+  An example of an alternate debugger is strace.  You can strace the
+  actual kernel as follows:
+
+  o  Run the following in a shell
+
+
+       host%
+       sh -c 'echo pid=$$; echo -n hit return; read x; exec strace -p 1 -o strace.out'
+
+
+
+  o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
+     by the previous command
+
+  o  Hit return in the shell, and UML will start running, and strace
+     output will start accumulating in the output file.
+
+     Note that this is different from running
+
+
+       host% strace ./linux
+
+
+
+
+  That will strace only the main UML thread, the tracing thread, which
+  doesn't do any of the actual kernel work.  It just oversees the vir-
+  tual machine.  In contrast, using strace as described above will show
+  you the low-level activity of the virtual machine.
+
+
+
+
+
+  12.  Kernel debugging examples
+
+  12.1.  The case of the hung fsck
+
+  When booting up the kernel, fsck failed, and dropped me into a shell
+  to fix things up.  I ran fsck -y, which hung:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Setting hostname uml                    [ OK ]
+  Checking root filesystem
+  /dev/fhd0 was not cleanly unmounted, check forced.
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
+
+  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
+          (i.e., without -a or -p options)
+  [ FAILED ]
+
+  *** An error occurred during the file system check.
+  *** Dropping you to a shell; the system will reboot
+  *** when you leave the shell.
+  Give root password for maintenance
+  (or type Control-D for normal startup):
+
+  [root@uml /root]# fsck -y /dev/fhd0
+  fsck -y /dev/fhd0
+  Parallelizing fsck version 1.14 (9-Jan-1999)
+  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
+  /dev/fhd0 contains a file system with errors, check forced.
+  Pass 1: Checking inodes, blocks, and sizes
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
+
+  Inode 19780, i_blocks is 1548, should be 540.  Fix? yes
+
+  Pass 2: Checking directory structure
+  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
+
+  Directory inode 11858, block 0, offset 0: directory corrupted
+  Salvage? yes
+
+  Missing '.' in directory inode 11858.
+  Fix? yes
+
+  Missing '..' in directory inode 11858.
+  Fix? yes
+
+
+
+
+
+  The standard drill in this sort of situation is to fire up gdb on the
+  signal thread, which, in this case, was pid 1935.  In another window,
+  I run gdb and attach pid 1935.
+
+
+
+
+       ~/linux/2.3.26/um 1016: gdb linux
+       GNU gdb 4.17.0.11 with Linux support
+       Copyright 1998 Free Software Foundation, Inc.
+       GDB is free software, covered by the GNU General Public License, and you are
+       welcome to change it and/or distribute copies of it under certain conditions.
+       Type "show copying" to see the conditions.
+       There is absolutely no warranty for GDB.  Type "show warranty" for details.
+       This GDB was configured as "i386-redhat-linux"...
+
+       (gdb) att 1935
+       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1935
+       0x100756d9 in __wait4 ()
+
+
+
+
+
+
+  Let's see what's currently running:
+
+
+
+       (gdb) p current_task.pid
+       $1 = 0
+
+
+
+
+
+  It's the idle thread, which means that fsck went to sleep for some
+  reason and never woke up.
+
+
+  Let's guess that the last process in the process list is fsck:
+
+
+
+       (gdb) p current_task.prev_task.comm
+       $13 = "fsck.ext2\000\000\000\000\000\000"
+
+
+
+
+
+  It is, so let's see what it thinks it's up to:
+
+
+
+       (gdb) p current_task.prev_task.thread
+       $14 = {extern_pid = 1980, tracing = 0, want_tracing = 0, forking = 0,
+         kernel_stack_page = 0, signal_stack = 1342627840, syscall = {id = 4, args = {
+             3, 134973440, 1024, 0, 1024}, have_result = 0, result = 50590720},
+         request = {op = 2, u = {exec = {ip = 1350467584, sp = 2952789424}, fork = {
+               regs = {1350467584, 2952789424, 0 <repeats 15 times>}, sigstack = 0,
+               pid = 0}, switch_to = 0x507e8000, thread = {proc = 0x507e8000,
+               arg = 0xaffffdb0, flags = 0, new_pid = 0}, input_request = {
+               op = 1350467584, fd = -1342177872, proc = 0, pid = 0}}}}
+
+
+
+
+
+  The interesting things here are the fact that its .thread.syscall.id
+  is __NR_write (see the big switch in arch/um/kernel/syscall_kern.c or
+  the defines in include/asm-um/arch/unistd.h), and that it never
+  returned.  Also, its .request.op is OP_SWITCH (see
+  arch/um/include/user_util.h).  These mean that it went into a write,
+  and, for some reason, called schedule().
+
+
+  The fact that it never returned from write means that its stack should
+  be fairly interesting.  Its pid is 1980 (.thread.extern_pid).  That
+  process is being ptraced by the signal thread, so it must be detached
+  before gdb can attach it:
+
+
+
+
+
+
+
+
+
+
+  (gdb) call detach(1980)
+
+  Program received signal SIGSEGV, Segmentation fault.
+  <function called from gdb>
+  The program being debugged stopped while in a function called from GDB.
+  When the function (detach) is done executing, GDB will silently
+  stop (instead of continuing to evaluate the expression containing
+  the function call).
+  (gdb) call detach(1980)
+  $15 = 0
+
+
+
+
+
+  The first detach segfaults for some reason, and the second one
+  succeeds.
+
+
+  Now I detach from the signal thread, attach to the fsck thread, and
+  look at its stack:
+
+
+       (gdb) det
+       Detaching from program: /home/dike/linux/2.3.26/um/linux Pid 1935
+       (gdb) att 1980
+       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1980
+       0x10070451 in __kill ()
+       (gdb) bt
+       #0  0x10070451 in __kill ()
+       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
+       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
+           at process_kern.c:156
+       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
+           at process_kern.c:161
+       #4  0x10001d12 in schedule () at core.c:777
+       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
+       #6  0x1006aa10 in __down_failed () at semaphore.c:157
+       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
+       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+       #9  <signal handler called>
+       #10 0x10155404 in errno ()
+       #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
+       #12 0x1006c5d8 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+       #13 0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+       #14 <signal handler called>
+       #15 0xc0fd in ?? ()
+       #16 0x10016647 in sys_write (fd=3,
+           buf=0x80b8800 <Address 0x80b8800 out of bounds>, count=1024)
+           at read_write.c:159
+       #17 0x1006d5b3 in execute_syscall (syscall=4, args=0x5006ef08)
+           at syscall_kern.c:254
+       #18 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
+       #19 <signal handler called>
+       #20 0x400dc8b0 in ?? ()
+
+
+
+
+
+  The interesting things here are :
+
+  o  There are two segfaults on this stack (frames 9 and 14)
+
+  o  The first faulting address (frame 11) is 0x50000800
+
+  (gdb) p (void *)1342179328
+  $16 = (void *) 0x50000800
+
+
+
+
+
+  The initial faulting address is interesting because it is on the idle
+  thread's stack.  I had been seeing the idle thread segfault for no
+  apparent reason, and the cause looked like stack corruption.  In hopes
+  of catching the culprit in the act, I had turned off all protections
+  to that stack while the idle thread wasn't running.  This apparently
+  tripped that trap.
+
+
+  However, the more immediate problem is that second segfault and I'm
+  going to concentrate on that.  First, I want to see where the fault
+  happened, so I have to go look at the sigcontent struct in frame 8:
+
+
+
+       (gdb) up
+       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
+       30        kill(pid, SIGUSR1);
+       (gdb)
+       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
+           at process_kern.c:156
+       156       usr1_pid(getpid());
+       (gdb)
+       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
+           at process_kern.c:161
+       161       _switch_to(prev, next);
+       (gdb)
+       #4  0x10001d12 in schedule () at core.c:777
+       777             switch_to(prev, next, prev);
+       (gdb)
+       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
+       71                      schedule();
+       (gdb)
+       #6  0x1006aa10 in __down_failed () at semaphore.c:157
+       157     }
+       (gdb)
+       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
+       174       segv(sc->cr2, sc->err & 2);
+       (gdb)
+       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+       182       segv_handler(sc);
+       (gdb) p *sc
+       Cannot access memory at address 0x0.
+
+
+
+
+  That's not very useful, so I'll try a more manual method:
+
+
+       (gdb) p *((struct sigcontext *) (&sig + 1))
+       $19 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
+         __dsh = 0, edi = 1342179328, esi = 1350378548, ebp = 1342630440,
+         esp = 1342630420, ebx = 1348150624, edx = 1280, ecx = 0, eax = 0,
+         trapno = 14, err = 4, eip = 268480945, cs = 35, __csh = 0, eflags = 66118,
+         esp_at_signal = 1342630420, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
+         cr2 = 1280}
+
+
+
+  The ip is in handle_mm_fault:
+
+
+       (gdb) p (void *)268480945
+       $20 = (void *) 0x1000b1b1
+       (gdb) i sym $20
+       handle_mm_fault + 57 in section .text
+
+
+
+
+
+  Specifically, it's in pte_alloc:
+
+
+       (gdb) i line *$20
+       Line 124 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1b1 <handle_mm_fault+57>
+          and ends at 0x1000b1b7 <handle_mm_fault+63>.
+
+
+
+
+
+  To find where in handle_mm_fault this is, I'll jump forward in the
+  code until I see an address in that procedure:
+
+
+
+       (gdb) i line *0x1000b1c0
+       Line 126 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1b7 <handle_mm_fault+63>
+          and ends at 0x1000b1c3 <handle_mm_fault+75>.
+       (gdb) i line *0x1000b1d0
+       Line 131 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1d0 <handle_mm_fault+88>
+          and ends at 0x1000b1da <handle_mm_fault+98>.
+       (gdb) i line *0x1000b1e0
+       Line 61 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1da <handle_mm_fault+98>
+          and ends at 0x1000b1e1 <handle_mm_fault+105>.
+       (gdb) i line *0x1000b1f0
+       Line 134 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b1f0 <handle_mm_fault+120>
+          and ends at 0x1000b200 <handle_mm_fault+136>.
+       (gdb) i line *0x1000b200
+       Line 135 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b200 <handle_mm_fault+136>
+          and ends at 0x1000b208 <handle_mm_fault+144>.
+       (gdb) i line *0x1000b210
+       Line 139 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+          starts at address 0x1000b210 <handle_mm_fault+152>
+          and ends at 0x1000b219 <handle_mm_fault+161>.
+       (gdb) i line *0x1000b220
+       Line 1168 of "memory.c" starts at address 0x1000b21e <handle_mm_fault+166>
+          and ends at 0x1000b222 <handle_mm_fault+170>.
+
+
+
+
+
+  Something is apparently wrong with the page tables or vma_structs, so
+  lets go back to frame 11 and have a look at them:
+
+
+
+  #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
+  50        handle_mm_fault(current, vma, address, is_write);
+  (gdb) call pgd_offset_proc(vma->vm_mm, address)
+  $22 = (pgd_t *) 0x80a548c
+
+
+
+
+
+  That's pretty bogus.  Page tables aren't supposed to be in process
+  text or data areas.  Let's see what's in the vma:
+
+
+       (gdb) p *vma
+       $23 = {vm_mm = 0x507d2434, vm_start = 0, vm_end = 134512640,
+         vm_next = 0x80a4f8c, vm_page_prot = {pgprot = 0}, vm_flags = 31200,
+         vm_avl_height = 2058, vm_avl_left = 0x80a8c94, vm_avl_right = 0x80d1000,
+         vm_next_share = 0xaffffdb0, vm_pprev_share = 0xaffffe63,
+         vm_ops = 0xaffffe7a, vm_pgoff = 2952789626, vm_file = 0xafffffec,
+         vm_private_data = 0x62}
+       (gdb) p *vma.vm_mm
+       $24 = {mmap = 0x507d2434, mmap_avl = 0x0, mmap_cache = 0x8048000,
+         pgd = 0x80a4f8c, mm_users = {counter = 0}, mm_count = {counter = 134904288},
+         map_count = 134909076, mmap_sem = {count = {counter = 135073792},
+           sleepers = -1342177872, wait = {lock = <optimized out or zero length>,
+             task_list = {next = 0xaffffe63, prev = 0xaffffe7a},
+             __magic = -1342177670, __creator = -1342177300}, __magic = 98},
+         page_table_lock = {}, context = 138, start_code = 0, end_code = 0,
+         start_data = 0, end_data = 0, start_brk = 0, brk = 0, start_stack = 0,
+         arg_start = 0, arg_end = 0, env_start = 0, env_end = 0, rss = 1350381536,
+         total_vm = 0, locked_vm = 0, def_flags = 0, cpu_vm_mask = 0, swap_cnt = 0,
+         swap_address = 0, segments = 0x0}
+
+
+
+
+
+  This also pretty bogus.  With all of the 0x80xxxxx and 0xaffffxxx
+  addresses, this is looking like a stack was plonked down on top of
+  these structures.  Maybe it's a stack overflow from the next page:
+
+
+
+       (gdb) p vma
+       $25 = (struct vm_area_struct *) 0x507d2434
+
+
+
+
+
+  That's towards the lower quarter of the page, so that would have to
+  have been pretty heavy stack overflow:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  (gdb) x/100x $25
+  0x507d2434:     0x507d2434      0x00000000      0x08048000      0x080a4f8c
+  0x507d2444:     0x00000000      0x080a79e0      0x080a8c94      0x080d1000
+  0x507d2454:     0xaffffdb0      0xaffffe63      0xaffffe7a      0xaffffe7a
+  0x507d2464:     0xafffffec      0x00000062      0x0000008a      0x00000000
+  0x507d2474:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2484:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2494:     0x00000000      0x00000000      0x507d2fe0      0x00000000
+  0x507d24a4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24b4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24c4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24d4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24e4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d24f4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2504:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2514:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2524:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2534:     0x00000000      0x00000000      0x507d25dc      0x00000000
+  0x507d2544:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2554:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2564:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2574:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2584:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d2594:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d25a4:     0x00000000      0x00000000      0x00000000      0x00000000
+  0x507d25b4:     0x00000000      0x00000000      0x00000000      0x00000000
+
+
+
+
+
+  It's not stack overflow.  The only "stack-like" piece of this data is
+  the vma_struct itself.
+
+
+  At this point, I don't see any avenues to pursue, so I just have to
+  admit that I have no idea what's going on.  What I will do, though, is
+  stick a trap on the segfault handler which will stop if it sees any
+  writes to the idle thread's stack.  That was the thing that happened
+  first, and it may be that if I can catch it immediately, what's going
+  on will be somewhat clearer.
+
+
+  12.2.  Episode 2: The case of the hung fsck
+
+  After setting a trap in the SEGV handler for accesses to the signal
+  thread's stack, I reran the kernel.
+
+
+  fsck hung again, this time by hitting the trap:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  Setting hostname uml                            [ OK ]
+  Checking root filesystem
+  /dev/fhd0 contains a file system with errors, check forced.
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
+
+  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
+          (i.e., without -a or -p options)
+  [ FAILED ]
+
+  *** An error occurred during the file system check.
+  *** Dropping you to a shell; the system will reboot
+  *** when you leave the shell.
+  Give root password for maintenance
+  (or type Control-D for normal startup):
+
+  [root@uml /root]# fsck -y /dev/fhd0
+  fsck -y /dev/fhd0
+  Parallelizing fsck version 1.14 (9-Jan-1999)
+  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
+  /dev/fhd0 contains a file system with errors, check forced.
+  Pass 1: Checking inodes, blocks, and sizes
+  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
+
+  Pass 2: Checking directory structure
+  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
+
+  Directory inode 11858, block 0, offset 0: directory corrupted
+  Salvage? yes
+
+  Missing '.' in directory inode 11858.
+  Fix? yes
+
+  Missing '..' in directory inode 11858.
+  Fix? yes
+
+  Untested (4127) [100fe44c]: trap_kern.c line 31
+
+
+
+
+
+  I need to get the signal thread to detach from pid 4127 so that I can
+  attach to it with gdb.  This is done by sending it a SIGUSR1, which is
+  caught by the signal thread, which detaches the process:
+
+
+       kill -USR1 4127
+
+
+
+
+
+  Now I can run gdb on it:
+
+
+
+
+
+
+
+
+
+
+
+
+
+  ~/linux/2.3.26/um 1034: gdb linux
+  GNU gdb 4.17.0.11 with Linux support
+  Copyright 1998 Free Software Foundation, Inc.
+  GDB is free software, covered by the GNU General Public License, and you are
+  welcome to change it and/or distribute copies of it under certain conditions.
+  Type "show copying" to see the conditions.
+  There is absolutely no warranty for GDB.  Type "show warranty" for details.
+  This GDB was configured as "i386-redhat-linux"...
+  (gdb) att 4127
+  Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 4127
+  0x10075891 in __libc_nanosleep ()
+
+
+
+
+
+  The backtrace shows that it was in a write and that the fault address
+  (address in frame 3) is 0x50000800, which is right in the middle of
+  the signal thread's stack page:
+
+
+       (gdb) bt
+       #0  0x10075891 in __libc_nanosleep ()
+       #1  0x1007584d in __sleep (seconds=1000000)
+           at ../sysdeps/unix/sysv/linux/sleep.c:78
+       #2  0x1006ce9a in stop () at user_util.c:191
+       #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
+       #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+       #5  0x1006c63c in kern_segv_handler (sig=11) at trap_user.c:182
+       #6  <signal handler called>
+       #7  0xc0fd in ?? ()
+       #8  0x10016647 in sys_write (fd=3, buf=0x80b8800 "R.", count=1024)
+           at read_write.c:159
+       #9  0x1006d603 in execute_syscall (syscall=4, args=0x5006ef08)
+           at syscall_kern.c:254
+       #10 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
+       #11 <signal handler called>
+       #12 0x400dc8b0 in ?? ()
+       #13 <signal handler called>
+       #14 0x400dc8b0 in ?? ()
+       #15 0x80545fd in ?? ()
+       #16 0x804daae in ?? ()
+       #17 0x8054334 in ?? ()
+       #18 0x804d23e in ?? ()
+       #19 0x8049632 in ?? ()
+       #20 0x80491d2 in ?? ()
+       #21 0x80596b5 in ?? ()
+       (gdb) p (void *)1342179328
+       $3 = (void *) 0x50000800
+
+
+
+
+
+  Going up the stack to the segv_handler frame and looking at where in
+  the code the access happened shows that it happened near line 110 of
+  block_dev.c:
+
+
+
+
+
+
+
+
+
+  (gdb) up
+  #1  0x1007584d in __sleep (seconds=1000000)
+      at ../sysdeps/unix/sysv/linux/sleep.c:78
+  ../sysdeps/unix/sysv/linux/sleep.c:78: No such file or directory.
+  (gdb)
+  #2  0x1006ce9a in stop () at user_util.c:191
+  191       while(1) sleep(1000000);
+  (gdb)
+  #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
+  31          KERN_UNTESTED();
+  (gdb)
+  #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+  174       segv(sc->cr2, sc->err & 2);
+  (gdb) p *sc
+  $1 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
+    __dsh = 0, edi = 1342179328, esi = 134973440, ebp = 1342631484,
+    esp = 1342630864, ebx = 256, edx = 0, ecx = 256, eax = 1024, trapno = 14,
+    err = 6, eip = 268550834, cs = 35, __csh = 0, eflags = 66070,
+    esp_at_signal = 1342630864, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
+    cr2 = 1342179328}
+  (gdb) p (void *)268550834
+  $2 = (void *) 0x1001c2b2
+  (gdb) i sym $2
+  block_write + 1090 in section .text
+  (gdb) i line *$2
+  Line 209 of "/home/dike/linux/2.3.26/um/include/asm/arch/string.h"
+     starts at address 0x1001c2a1 <block_write+1073>
+     and ends at 0x1001c2bf <block_write+1103>.
+  (gdb) i line *0x1001c2c0
+  Line 110 of "block_dev.c" starts at address 0x1001c2bf <block_write+1103>
+     and ends at 0x1001c2e3 <block_write+1139>.
+
+
+
+
+
+  Looking at the source shows that the fault happened during a call to
+  copy_from_user to copy the data into the kernel:
+
+
+       107             count -= chars;
+       108             copy_from_user(p,buf,chars);
+       109             p += chars;
+       110             buf += chars;
+
+
+
+
+
+  p is the pointer which must contain 0x50000800, since buf contains
+  0x80b8800 (frame 8 above).  It is defined as:
+
+
+                       p = offset + bh->b_data;
+
+
+
+
+
+  I need to figure out what bh is, and it just so happens that bh is
+  passed as an argument to mark_buffer_uptodate and mark_buffer_dirty a
+  few lines later, so I do a little disassembly:
+
+
+
+
+  (gdb) disas 0x1001c2bf 0x1001c2e0
+  Dump of assembler code from 0x1001c2bf to 0x1001c2d0:
+  0x1001c2bf <block_write+1103>:  addl   %eax,0xc(%ebp)
+  0x1001c2c2 <block_write+1106>:  movl   0xfffffdd4(%ebp),%edx
+  0x1001c2c8 <block_write+1112>:  btsl   $0x0,0x18(%edx)
+  0x1001c2cd <block_write+1117>:  btsl   $0x1,0x18(%edx)
+  0x1001c2d2 <block_write+1122>:  sbbl   %ecx,%ecx
+  0x1001c2d4 <block_write+1124>:  testl  %ecx,%ecx
+  0x1001c2d6 <block_write+1126>:  jne    0x1001c2e3 <block_write+1139>
+  0x1001c2d8 <block_write+1128>:  pushl  $0x0
+  0x1001c2da <block_write+1130>:  pushl  %edx
+  0x1001c2db <block_write+1131>:  call   0x1001819c <__mark_buffer_dirty>
+  End of assembler dump.
+
+
+
+
+
+  At that point, bh is in %edx (address 0x1001c2da), which is calculated
+  at 0x1001c2c2 as %ebp + 0xfffffdd4, so I figure exactly what that is,
+  taking %ebp from the sigcontext_struct above:
+
+
+       (gdb) p (void *)1342631484
+       $5 = (void *) 0x5006ee3c
+       (gdb) p 0x5006ee3c+0xfffffdd4
+       $6 = 1342630928
+       (gdb) p (void *)$6
+       $7 = (void *) 0x5006ec10
+       (gdb) p *((void **)$7)
+       $8 = (void *) 0x50100200
+
+
+
+
+
+  Now, I look at the structure to see what's in it, and particularly,
+  what its b_data field contains:
+
+
+       (gdb) p *((struct buffer_head *)0x50100200)
+       $13 = {b_next = 0x50289380, b_blocknr = 49405, b_size = 1024, b_list = 0,
+         b_dev = 15872, b_count = {counter = 1}, b_rdev = 15872, b_state = 24,
+         b_flushtime = 0, b_next_free = 0x501001a0, b_prev_free = 0x50100260,
+         b_this_page = 0x501001a0, b_reqnext = 0x0, b_pprev = 0x507fcf58,
+         b_data = 0x50000800 "", b_page = 0x50004000,
+         b_end_io = 0x10017f60 <end_buffer_io_sync>, b_dev_id = 0x0,
+         b_rsector = 98810, b_wait = {lock = <optimized out or zero length>,
+           task_list = {next = 0x50100248, prev = 0x50100248}, __magic = 1343226448,
+           __creator = 0}, b_kiobuf = 0x0}
+
+
+
+
+
+  The b_data field is indeed 0x50000800, so the question becomes how
+  that happened.  The rest of the structure looks fine, so this probably
+  is not a case of data corruption.  It happened on purpose somehow.
+
+
+  The b_page field is a pointer to the page_struct representing the
+  0x50000000 page.  Looking at it shows the kernel's idea of the state
+  of that page:
+
+
+
+  (gdb) p *$13.b_page
+  $17 = {list = {next = 0x50004a5c, prev = 0x100c5174}, mapping = 0x0,
+    index = 0, next_hash = 0x0, count = {counter = 1}, flags = 132, lru = {
+      next = 0x50008460, prev = 0x50019350}, wait = {
+      lock = <optimized out or zero length>, task_list = {next = 0x50004024,
+        prev = 0x50004024}, __magic = 1342193708, __creator = 0},
+    pprev_hash = 0x0, buffers = 0x501002c0, virtual = 1342177280,
+    zone = 0x100c5160}
+
+
+
+
+
+  Some sanity-checking: the virtual field shows the "virtual" address of
+  this page, which in this kernel is the same as its "physical" address,
+  and the page_struct itself should be mem_map[0], since it represents
+  the first page of memory:
+
+
+
+       (gdb) p (void *)1342177280
+       $18 = (void *) 0x50000000
+       (gdb) p mem_map
+       $19 = (mem_map_t *) 0x50004000
+
+
+
+
+
+  These check out fine.
+
+
+  Now to check out the page_struct itself.  In particular, the flags
+  field shows whether the page is considered free or not:
+
+
+       (gdb) p (void *)132
+       $21 = (void *) 0x84
+
+
+
+
+
+  The "reserved" bit is the high bit, which is definitely not set, so
+  the kernel considers the signal stack page to be free and available to
+  be used.
+
+
+  At this point, I jump to conclusions and start looking at my early
+  boot code, because that's where that page is supposed to be reserved.
+
+
+  In my setup_arch procedure, I have the following code which looks just
+  fine:
+
+
+
+       bootmap_size = init_bootmem(start_pfn, end_pfn - start_pfn);
+       free_bootmem(__pa(low_physmem) + bootmap_size, high_physmem - low_physmem);
+
+
+
+
+
+  Two stack pages have already been allocated, and low_physmem points to
+  the third page, which is the beginning of free memory.
+  The init_bootmem call declares the entire memory to the boot memory
+  manager, which marks it all reserved.  The free_bootmem call frees up
+  all of it, except for the first two pages.  This looks correct to me.
+
+
+  So, I decide to see init_bootmem run and make sure that it is marking
+  those first two pages as reserved.  I never get that far.
+
+
+  Stepping into init_bootmem, and looking at bootmem_map before looking
+  at what it contains shows the following:
+
+
+
+       (gdb) p bootmem_map
+       $3 = (void *) 0x50000000
+
+
+
+
+
+  Aha!  The light dawns.  That first page is doing double duty as a
+  stack and as the boot memory map.  The last thing that the boot memory
+  manager does is to free the pages used by its memory map, so this page
+  is getting freed even its marked as reserved.
+
+
+  The fix was to initialize the boot memory manager before allocating
+  those two stack pages, and then allocate them through the boot memory
+  manager.  After doing this, and fixing a couple of subsequent buglets,
+  the stack corruption problem disappeared.
+
+
+
+
+
+  13.  What to do when UML doesn't work
+
+
+
+
+  13.1.  Strange compilation errors when you build from source
+
+  As of test11, it is necessary to have "ARCH=um" in the environment or
+  on the make command line for all steps in building UML, including
+  clean, distclean, or mrproper, config, menuconfig, or xconfig, dep,
+  and linux.  If you forget for any of them, the i386 build seems to
+  contaminate the UML build.  If this happens, start from scratch with
+
+
+       host%
+       make mrproper ARCH=um
+
+
+
+
+  and repeat the build process with ARCH=um on all the steps.
+
+
+  See ``Compiling the kernel and modules''  for more details.
+
+
+  Another cause of strange compilation errors is building UML in
+  /usr/src/linux.  If you do this, the first thing you need to do is
+  clean up the mess you made.  The /usr/src/linux/asm link will now
+  point to /usr/src/linux/asm-um.  Make it point back to
+  /usr/src/linux/asm-i386.  Then, move your UML pool someplace else and
+  build it there.  Also see below, where a more specific set of symptoms
+  is described.
+
+
+
+  13.3.  A variety of panics and hangs with /tmp on a reiserfs  filesys-
+  tem
+
+  I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
+  Panics preceded by
+
+
+       Detaching pid nnnn
+
+
+
+  are diagnostic of this problem.  This is a reiserfs bug which causes a
+  thread to occasionally read stale data from a mmapped page shared with
+  another thread.  The fix is to upgrade the filesystem or to have /tmp
+  be an ext2 filesystem.
+
+
+
+  13.4.  The compile fails with errors about conflicting types for
+  'open', 'dup', and 'waitpid'
+
+  This happens when you build in /usr/src/linux.  The UML build makes
+  the include/asm link point to include/asm-um.  /usr/include/asm points
+  to /usr/src/linux/include/asm, so when that link gets moved, files
+  which need to include the asm-i386 versions of headers get the
+  incompatible asm-um versions.  The fix is to move the include/asm link
+  back to include/asm-i386 and to do UML builds someplace else.
+
+
+
+  13.5.  UML doesn't work when /tmp is an NFS filesystem
+
+  This seems to be a similar situation with the ReiserFS problem above.
+  Some versions of NFS seems not to handle mmap correctly, which UML
+  depends on.  The workaround is have /tmp be a non-NFS directory.
+
+
+  13.6.  UML hangs on boot when compiled with gprof support
+
+  If you build UML with gprof support and, early in the boot, it does
+  this
+
+
+       kernel BUG at page_alloc.c:100!
+
+
+
+
+  you have a buggy gcc.  You can work around the problem by removing
+  UM_FASTCALL from CFLAGS in arch/um/Makefile-i386.  This will open up
+  another bug, but that one is fairly hard to reproduce.
+
+
+
+  13.7.  syslogd dies with a SIGTERM on startup
+
+  The exact boot error depends on the distribution that you're booting,
+  but Debian produces this:
+
+
+       /etc/rc2.d/S10sysklogd: line 49:    93 Terminated
+       start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD
+
+
+
+
+  This is a syslogd bug.  There's a race between a parent process
+  installing a signal handler and its child sending the signal.  See
+  this uml-devel post <http://www.geocrawler.com/lists/3/Source-
+  Forge/709/0/6612801>  for the details.
+
+
+
+  13.8.  TUN/TAP networking doesn't work on a 2.4 host
+
+  There are a couple of problems which were
+  <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
+  out">  by Tim Robinson <timro at trkr dot net>
+
+  o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
+     The fix is to upgrade to something more recent and then read the
+     next item.
+
+  o  If you see
+
+
+       File descriptor in bad state
+
+
+
+  when you bring up the device inside UML, you have a header mismatch
+  between the original kernel and the upgraded one.  Make /usr/src/linux
+  point at the new headers.  This will only be a problem if you build
+  uml_net yourself.
+
+
+
+  13.9.  You can network to the host but not to other machines on the
+  net
+
+  If you can connect to the host, and the host can connect to UML, but
+  you cannot connect to any other machines, then you may need to enable
+  IP Masquerading on the host.  Usually this is only experienced when
+  using private IP addresses (192.168.x.x or 10.x.x.x) for host/UML
+  networking, rather than the public address space that your host is
+  connected to.  UML does not enable IP Masquerading, so you will need
+  to create a static rule to enable it:
+
+
+       host%
+       iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+
+
+
+
+  Replace eth0 with the interface that you use to talk to the rest of
+  the world.
+
+
+  Documentation on IP Masquerading, and SNAT, can be found at
+  www.netfilter.org  <http://www.netfilter.org> .
+
+
+  If you can reach the local net, but not the outside Internet, then
+  that is usually a routing problem.  The UML needs a default route:
+
+
+       UML#
+       route add default gw gateway IP
+
+
+
+
+  The gateway IP can be any machine on the local net that knows how to
+  reach the outside world.  Usually, this is the host or the local net-
+  work's gateway.
+
+
+  Occasionally, we hear from someone who can reach some machines, but
+  not others on the same net, or who can reach some ports on other
+  machines, but not others.  These are usually caused by strange
+  firewalling somewhere between the UML and the other box.  You track
+  this down by running tcpdump on every interface the packets travel
+  over and see where they disappear.  When you find a machine that takes
+  the packets in, but does not send them onward, that's the culprit.
+
+
+
+  13.10.  I have no root and I want to scream
+
+  Thanks to Birgit Wahlich for telling me about this strange one.  It
+  turns out that there's a limit of six environment variables on the
+  kernel command line.  When that limit is reached or exceeded, argument
+  processing stops, which means that the 'root=' argument that UML
+  usually adds is not seen.  So, the filesystem has no idea what the
+  root device is, so it panics.
+
+
+  The fix is to put less stuff on the command line.  Glomming all your
+  setup variables into one is probably the best way to go.
+
+
+
+  13.11.  UML build conflict between ptrace.h and ucontext.h
+
+  On some older systems, /usr/include/asm/ptrace.h and
+  /usr/include/sys/ucontext.h define the same names.  So, when they're
+  included together, the defines from one completely mess up the parsing
+  of the other, producing errors like:
+       /usr/include/sys/ucontext.h:47: parse error before
+       `10'
+
+
+
+
+  plus a pile of warnings.
+
+
+  This is a libc botch, which has since been fixed, and I don't see any
+  way around it besides upgrading.
+
+
+
+  13.12.  The UML BogoMips is exactly half the host's BogoMips
+
+  On i386 kernels, there are two ways of running the loop that is used
+  to calculate the BogoMips rating, using the TSC if it's there or using
+  a one-instruction loop.  The TSC produces twice the BogoMips as the
+  loop.  UML uses the loop, since it has nothing resembling a TSC, and
+  will get almost exactly the same BogoMips as a host using the loop.
+  However, on a host with a TSC, its BogoMips will be double the loop
+  BogoMips, and therefore double the UML BogoMips.
+
+
+
+  13.13.  When you run UML, it immediately segfaults
+
+  If the host is configured with the 2G/2G address space split, that's
+  why.  See ``UML on 2G/2G hosts''  for the details on getting UML to
+  run on your host.
+
+
+
+  13.14.  xterms appear, then immediately disappear
+
+  If you're running an up to date kernel with an old release of
+  uml_utilities, the port-helper program will not work properly, so
+  xterms will exit straight after they appear. The solution is to
+  upgrade to the latest release of uml_utilities.  Usually this problem
+  occurs when you have installed a packaged release of UML then compiled
+  your own development kernel without upgrading the uml_utilities from
+  the source distribution.
+
+
+
+  13.15.  Any other panic, hang, or strange behavior
+
+  If you're seeing truly strange behavior, such as hangs or panics that
+  happen in random places, or you try running the debugger to see what's
+  happening and it acts strangely, then it could be a problem in the
+  host kernel.  If you're not running a stock Linus or -ac kernel, then
+  try that.  An early version of the preemption patch and a 2.4.10 SuSE
+  kernel have caused very strange problems in UML.
+
+
+  Otherwise, let me know about it.  Send a message to one of the UML
+  mailing lists - either the developer list - user-mode-linux-devel at
+  lists dot sourceforge dot net (subscription info) or the user list -
+  user-mode-linux-user at lists dot sourceforge do net (subscription
+  info), whichever you prefer.  Don't assume that everyone knows about
+  it and that a fix is imminent.
+
+
+  If you want to be super-helpful, read ``Diagnosing Problems'' and
+  follow the instructions contained therein.
+  14.  Diagnosing Problems
+
+
+  If you get UML to crash, hang, or otherwise misbehave, you should
+  report this on one of the project mailing lists, either the developer
+  list - user-mode-linux-devel at lists dot sourceforge dot net
+  (subscription info) or the user list - user-mode-linux-user at lists
+  dot sourceforge dot net (subscription info).  When you do, it is
+  likely that I will want more information.  So, it would be helpful to
+  read the stuff below, do whatever is applicable in your case, and
+  report the results to the list.
+
+
+  For any diagnosis, you're going to need to build a debugging kernel.
+  The binaries from this site aren't debuggable.  If you haven't done
+  this before, read about ``Compiling the kernel and modules''  and
+  ``Kernel debugging''  UML first.
+
+
+  14.1.  Case 1 : Normal kernel panics
+
+  The most common case is for a normal thread to panic.  To debug this,
+  you will need to run it under the debugger (add 'debug' to the command
+  line).  An xterm will start up with gdb running inside it.  Continue
+  it when it stops in start_kernel and make it crash.  Now ^C gdb and
+
+
+  If the panic was a "Kernel mode fault", then there will be a segv
+  frame on the stack and I'm going to want some more information.  The
+  stack might look something like this:
+
+
+       (UML gdb)  backtrace
+       #0  0x1009bf76 in __sigprocmask (how=1, set=0x5f347940, oset=0x0)
+           at ../sysdeps/unix/sysv/linux/sigprocmask.c:49
+       #1  0x10091411 in change_sig (signal=10, on=1) at process.c:218
+       #2  0x10094785 in timer_handler (sig=26) at time_kern.c:32
+       #3  0x1009bf38 in __restore ()
+           at ../sysdeps/unix/sysv/linux/i386/sigaction.c:125
+       #4  0x1009534c in segv (address=8, ip=268849158, is_write=2, is_user=0)
+           at trap_kern.c:66
+       #5  0x10095c04 in segv_handler (sig=11) at trap_user.c:285
+       #6  0x1009bf38 in __restore ()
+
+
+
+
+  I'm going to want to see the symbol and line information for the value
+  of ip in the segv frame.  In this case, you would do the following:
+
+
+       (UML gdb)  i sym 268849158
+
+
+
+
+  and
+
+
+       (UML gdb)  i line *268849158
+
+
+
+
+  The reason for this is the __restore frame right above the segv_han-
+  dler frame is hiding the frame that actually segfaulted.  So, I have
+  to get that information from the faulting ip.
+
+
+  14.2.  Case 2 : Tracing thread panics
+
+  The less common and more painful case is when the tracing thread
+  panics.  In this case, the kernel debugger will be useless because it
+  needs a healthy tracing thread in order to work.  The first thing to
+  do is get a backtrace from the tracing thread.  This is done by
+  figuring out what its pid is, firing up gdb, and attaching it to that
+  pid.  You can figure out the tracing thread pid by looking at the
+  first line of the console output, which will look like this:
+
+
+       tracing thread pid = 15851
+
+
+
+
+  or by running ps on the host and finding the line that looks like
+  this:
+
+
+       jdike 15851 4.5 0.4 132568 1104 pts/0 S 21:34 0:05 ./linux [(tracing thread)]
+
+
+
+
+  If the panic was 'segfault in signals', then follow the instructions
+  above for collecting information about the location of the seg fault.
+
+
+  If the tracing thread flaked out all by itself, then send that
+  backtrace in and wait for our crack debugging team to fix the problem.
+
+
+  14.3.  Case 3 : Tracing thread panics caused by other threads
+
+  However, there are cases where the misbehavior of another thread
+  caused the problem.  The most common panic of this type is:
+
+
+       wait_for_stop failed to wait for  <pid>  to stop with  <signal number>
+
+
+
+
+  In this case, you'll need to get a backtrace from the process men-
+  tioned in the panic, which is complicated by the fact that the kernel
+  debugger is defunct and without some fancy footwork, another gdb can't
+  attach to it.  So, this is how the fancy footwork goes:
+
+  In a shell:
+
+
+       host% kill -STOP pid
+
+
+
+
+  Run gdb on the tracing thread as described in case 2 and do:
+
+
+       (host gdb)  call detach(pid)
+
+
+  If you get a segfault, do it again.  It always works the second time.
+
+  Detach from the tracing thread and attach to that other thread:
+
+
+       (host gdb)  detach
+
+
+
+
+
+
+       (host gdb)  attach pid
+
+
+
+
+  If gdb hangs when attaching to that process, go back to a shell and
+  do:
+
+
+       host%
+       kill -CONT pid
+
+
+
+
+  And then get the backtrace:
+
+
+       (host gdb)  backtrace
+
+
+
+
+
+  14.4.  Case 4 : Hangs
+
+  Hangs seem to be fairly rare, but they sometimes happen.  When a hang
+  happens, we need a backtrace from the offending process.  Run the
+  kernel debugger as described in case 1 and get a backtrace.  If the
+  current process is not the idle thread, then send in the backtrace.
+  You can tell that it's the idle thread if the stack looks like this:
+
+
+       #0  0x100b1401 in __libc_nanosleep ()
+       #1  0x100a2885 in idle_sleep (secs=10) at time.c:122
+       #2  0x100a546f in do_idle () at process_kern.c:445
+       #3  0x100a5508 in cpu_idle () at process_kern.c:471
+       #4  0x100ec18f in start_kernel () at init/main.c:592
+       #5  0x100a3e10 in start_kernel_proc (unused=0x0) at um_arch.c:71
+       #6  0x100a383f in signal_tramp (arg=0x100a3dd8) at trap_user.c:50
+
+
+
+
+  If this is the case, then some other process is at fault, and went to
+  sleep when it shouldn't have.  Run ps on the host and figure out which
+  process should not have gone to sleep and stayed asleep.  Then attach
+  to it with gdb and get a backtrace as described in case 3.
+
+
+
+
+
+
+  15.  Thanks
+
+
+  A number of people have helped this project in various ways, and this
+  page gives recognition where recognition is due.
+
+
+  If you're listed here and you would prefer a real link on your name,
+  or no link at all, instead of the despammed email address pseudo-link,
+  let me know.
+
+
+  If you're not listed here and you think maybe you should be, please
+  let me know that as well.  I try to get everyone, but sometimes my
+  bookkeeping lapses and I forget about contributions.
+
+
+  15.1.  Code and Documentation
+
+  Rusty Russell <rusty at linuxcare.com.au>  -
+
+  o  wrote the  HOWTO <http://user-mode-
+     linux.sourceforge.net/UserModeLinux-HOWTO.html>
+
+  o  prodded me into making this project official and putting it on
+     SourceForge
+
+  o  came up with the way cool UML logo <http://user-mode-
+     linux.sourceforge.net/uml-small.png>
+
+  o  redid the config process
+
+
+  Peter Moulder <reiter at netspace.net.au>  - Fixed my config and build
+  processes, and added some useful code to the block driver
+
+
+  Bill Stearns <wstearns at pobox.com>  -
+
+  o  HOWTO updates
+
+  o  lots of bug reports
+
+  o  lots of testing
+
+  o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
+
+  o  wrote the mkrootfs script, which allows bootable filesystems of
+     RPM-based distributions to be cranked out
+
+  o  cranked out a large number of filesystems with said script
+
+
+  Jim Leu <jleu at mindspring.com>  - Wrote the virtual ethernet driver
+  and associated usermode tools
+
+  Lars Brinkhoff <http://lars.nocrew.org/>  - Contributed the ptrace
+  proxy from his own  project <http://a386.nocrew.org/> to allow easier
+  kernel debugging
+
+
+  Andrea Arcangeli <andrea at suse.de>  - Redid some of the early boot
+  code so that it would work on machines with Large File Support
+
+
+  Chris Emerson <http://www.chiark.greenend.org.uk/~cemerson/>  - Did
+  the first UML port to Linux/ppc
+
+
+  Harald Welte <laforge at gnumonks.org>  - Wrote the multicast
+  transport for the network driver
+
+
+  Jorgen Cederlof - Added special file support to hostfs
+
+
+  Greg Lonnon  <glonnon at ridgerun dot com>  - Changed the ubd driver
+  to allow it to layer a COW file on a shared read-only filesystem and
+  wrote the iomem emulation support
+
+
+  Henrik Nordstrom <http://hem.passagen.se/hno/>  - Provided a variety
+  of patches, fixes, and clues
+
+
+  Lennert Buytenhek - Contributed various patches, a rewrite of the
+  network driver, the first implementation of the mconsole driver, and
+  did the bulk of the work needed to get SMP working again.
+
+
+  Yon Uriarte - Fixed the TUN/TAP network backend while I slept.
+
+
+  Adam Heath - Made a bunch of nice cleanups to the initialization code,
+  plus various other small patches.
+
+
+  Matt Zimmerman - Matt volunteered to be the UML Debian maintainer and
+  is doing a real nice job of it.  He also noticed and fixed a number of
+  actually and potentially exploitable security holes in uml_net.  Plus
+  the occasional patch.  I like patches.
+
+
+  James McMechan - James seems to have taken over maintenance of the ubd
+  driver and is doing a nice job of it.
+
+
+  Chandan Kudige - wrote the umlgdb script which automates the reloading
+  of module symbols.
+
+
+  Steve Schmidtke - wrote the UML slirp transport and hostaudio drivers,
+  enabling UML processes to access audio devices on the host. He also
+  submitted patches for the slip transport and lots of other things.
+
+
+  David Coulson <http://davidcoulson.net>  -
+
+  o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
+     which is a great way of keeping the UML user community on top of
+     UML goings-on.
+
+  o  Site documentation and updates
+
+  o  Nifty little UML management daemon  UMLd
+     <http://uml.openconsultancy.com/umld/>
+
+  o  Lots of testing and bug reports
+
+
+
+
+  15.2.  Flushing out bugs
+
+
+
+  o  Yuri Pudgorodsky
+
+  o  Gerald Britton
+
+  o  Ian Wehrman
+
+  o  Gord Lamb
+
+  o  Eugene Koontz
+
+  o  John H. Hartman
+
+  o  Anders Karlsson
+
+  o  Daniel Phillips
+
+  o  John Fremlin
+
+  o  Rainer Burgstaller
+
+  o  James Stevenson
+
+  o  Matt Clay
+
+  o  Cliff Jefferies
+
+  o  Geoff Hoff
+
+  o  Lennert Buytenhek
+
+  o  Al Viro
+
+  o  Frank Klingenhoefer
+
+  o  Livio Baldini Soares
+
+  o  Jon Burgess
+
+  o  Petru Paler
+
+  o  Paul
+
+  o  Chris Reahard
+
+  o  Sverker Nilsson
+
+  o  Gong Su
+
+  o  johan verrept
+
+  o  Bjorn Eriksson
+
+  o  Lorenzo Allegrucci
+
+  o  Muli Ben-Yehuda
+
+  o  David Mansfield
+
+  o  Howard Goff
+
+  o  Mike Anderson
+
+  o  John Byrne
+
+  o  Sapan J. Batia
+
+  o  Iris Huang
+
+  o  Jan Hudec
+
+  o  Voluspa
+
+
+
+
+  15.3.  Buglets and clean-ups
+
+
+
+  o  Dave Zarzycki
+
+  o  Adam Lazur
+
+  o  Boria Feigin
+
+  o  Brian J. Murrell
+
+  o  JS
+
+  o  Roman Zippel
+
+  o  Wil Cooley
+
+  o  Ayelet Shemesh
+
+  o  Will Dyson
+
+  o  Sverker Nilsson
+
+  o  dvorak
+
+  o  v.naga srinivas
+
+  o  Shlomi Fish
+
+  o  Roger Binns
+
+  o  johan verrept
+
+  o  MrChuoi
+
+  o  Peter Cleve
+
+  o  Vincent Guffens
+
+  o  Nathan Scott
+
+  o  Patrick Caulfield
+
+  o  jbearce
+
+  o  Catalin Marinas
+
+  o  Shane Spencer
+
+  o  Zou Min
+
+
+  o  Ryan Boder
+
+  o  Lorenzo Colitti
+
+  o  Gwendal Grignou
+
+  o  Andre' Breiler
+
+  o  Tsutomu Yasuda
+
+
+
+  15.4.  Case Studies
+
+
+  o  Jon Wright
+
+  o  William McEwan
+
+  o  Michael Richardson
+
+
+
+  15.5.  Other contributions
+
+
+  Bill Carr <Bill.Carr at compaq.com>  made the Red Hat mkrootfs script
+  work with RH 6.2.
+
+  Michael Jennings <mikejen at hevanet.com>  sent in some material which
+  is now gracing the top of the  index  page <http://user-mode-
+  linux.sourceforge.net/>  of this site.
+
+  SGI <http://www.sgi.com>  (and more specifically Ralf Baechle <ralf at
+  uni-koblenz.de> ) gave me an account on oss.sgi.com
+  <http://www.oss.sgi.com> .  The bandwidth there made it possible to
+  produce most of the filesystems available on the project download
+  page.
+
+  Laurent Bonnaud <Laurent.Bonnaud at inpg.fr>  took the old grotty
+  Debian filesystem that I've been distributing and updated it to 2.2.
+  It is now available by itself here.
+
+  Rik van Riel gave me some ftp space on ftp.nl.linux.org so I can make
+  releases even when Sourceforge is broken.
+
+  Rodrigo de Castro looked at my broken pte code and told me what was
+  wrong with it, letting me fix a long-standing (several weeks) and
+  serious set of bugs.
+
+  Chris Reahard built a specialized root filesystem for running a DNS
+  server jailed inside UML.  It's available from the download
+  <http://user-mode-linux.sourceforge.net/dl-sf.html>  page in the Jail
+  Filesystems section.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Documentation/virtual/index.rst b/Documentation/virtual/index.rst
deleted file mode 100644 (file)
index 062ffb5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============================
-Linux Virtualization Support
-============================
-
-.. toctree::
-   :maxdepth: 2
-
-   kvm/index
-   paravirt_ops
-
-.. only:: html and subproject
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/virtual/kvm/amd-memory-encryption.rst b/Documentation/virtual/kvm/amd-memory-encryption.rst
deleted file mode 100644 (file)
index d18c97b..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-======================================
-Secure Encrypted Virtualization (SEV)
-======================================
-
-Overview
-========
-
-Secure Encrypted Virtualization (SEV) is a feature found on AMD processors.
-
-SEV is an extension to the AMD-V architecture which supports running
-virtual machines (VMs) under the control of a hypervisor. When enabled,
-the memory contents of a VM will be transparently encrypted with a key
-unique to that VM.
-
-The hypervisor can determine the SEV support through the CPUID
-instruction. The CPUID function 0x8000001f reports information related
-to SEV::
-
-       0x8000001f[eax]:
-                       Bit[1]  indicates support for SEV
-           ...
-                 [ecx]:
-                       Bits[31:0]  Number of encrypted guests supported simultaneously
-
-If support for SEV is present, MSR 0xc001_0010 (MSR_K8_SYSCFG) and MSR 0xc001_0015
-(MSR_K7_HWCR) can be used to determine if it can be enabled::
-
-       0xc001_0010:
-               Bit[23]    1 = memory encryption can be enabled
-                          0 = memory encryption can not be enabled
-
-       0xc001_0015:
-               Bit[0]     1 = memory encryption can be enabled
-                          0 = memory encryption can not be enabled
-
-When SEV support is available, it can be enabled in a specific VM by
-setting the SEV bit before executing VMRUN.::
-
-       VMCB[0x90]:
-               Bit[1]      1 = SEV is enabled
-                           0 = SEV is disabled
-
-SEV hardware uses ASIDs to associate a memory encryption key with a VM.
-Hence, the ASID for the SEV-enabled guests must be from 1 to a maximum value
-defined in the CPUID 0x8000001f[ecx] field.
-
-SEV Key Management
-==================
-
-The SEV guest key management is handled by a separate processor called the AMD
-Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a secure
-key management interface to perform common hypervisor activities such as
-encrypting bootstrap code, snapshot, migrating and debugging the guest. For more
-information, see the SEV Key Management spec [api-spec]_
-
-KVM implements the following commands to support common lifecycle events of SEV
-guests, such as launching, running, snapshotting, migrating and decommissioning.
-
-1. KVM_SEV_INIT
----------------
-
-The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform
-context. In a typical workflow, this command should be the first command issued.
-
-Returns: 0 on success, -negative on error
-
-2. KVM_SEV_LAUNCH_START
------------------------
-
-The KVM_SEV_LAUNCH_START command is used for creating the memory encryption
-context. To create the encryption context, user must provide a guest policy,
-the owner's public Diffie-Hellman (PDH) key and session information.
-
-Parameters: struct  kvm_sev_launch_start (in/out)
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_start {
-                __u32 handle;           /* if zero then firmware creates a new handle */
-                __u32 policy;           /* guest's policy */
-
-                __u64 dh_uaddr;         /* userspace address pointing to the guest owner's PDH key */
-                __u32 dh_len;
-
-                __u64 session_addr;     /* userspace address which points to the guest session information */
-                __u32 session_len;
-        };
-
-On success, the 'handle' field contains a new handle and on error, a negative value.
-
-For more details, see SEV spec Section 6.2.
-
-3. KVM_SEV_LAUNCH_UPDATE_DATA
------------------------------
-
-The KVM_SEV_LAUNCH_UPDATE_DATA is used for encrypting a memory region. It also
-calculates a measurement of the memory contents. The measurement is a signature
-of the memory contents that can be sent to the guest owner as an attestation
-that the memory was encrypted correctly by the firmware.
-
-Parameters (in): struct  kvm_sev_launch_update_data
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_update {
-                __u64 uaddr;    /* userspace address to be encrypted (must be 16-byte aligned) */
-                __u32 len;      /* length of the data to be encrypted (must be 16-byte aligned) */
-        };
-
-For more details, see SEV spec Section 6.3.
-
-4. KVM_SEV_LAUNCH_MEASURE
--------------------------
-
-The KVM_SEV_LAUNCH_MEASURE command is used to retrieve the measurement of the
-data encrypted by the KVM_SEV_LAUNCH_UPDATE_DATA command. The guest owner may
-wait to provide the guest with confidential information until it can verify the
-measurement. Since the guest owner knows the initial contents of the guest at
-boot, the measurement can be verified by comparing it to what the guest owner
-expects.
-
-Parameters (in): struct  kvm_sev_launch_measure
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_measure {
-                __u64 uaddr;    /* where to copy the measurement */
-                __u32 len;      /* length of measurement blob */
-        };
-
-For more details on the measurement verification flow, see SEV spec Section 6.4.
-
-5. KVM_SEV_LAUNCH_FINISH
-------------------------
-
-After completion of the launch flow, the KVM_SEV_LAUNCH_FINISH command can be
-issued to make the guest ready for the execution.
-
-Returns: 0 on success, -negative on error
-
-6. KVM_SEV_GUEST_STATUS
------------------------
-
-The KVM_SEV_GUEST_STATUS command is used to retrieve status information about a
-SEV-enabled guest.
-
-Parameters (out): struct kvm_sev_guest_status
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_guest_status {
-                __u32 handle;   /* guest handle */
-                __u32 policy;   /* guest policy */
-                __u8 state;     /* guest state (see enum below) */
-        };
-
-SEV guest state:
-
-::
-
-        enum {
-        SEV_STATE_INVALID = 0;
-        SEV_STATE_LAUNCHING,    /* guest is currently being launched */
-        SEV_STATE_SECRET,       /* guest is being launched and ready to accept the ciphertext data */
-        SEV_STATE_RUNNING,      /* guest is fully launched and running */
-        SEV_STATE_RECEIVING,    /* guest is being migrated in from another SEV machine */
-        SEV_STATE_SENDING       /* guest is getting migrated out to another SEV machine */
-        };
-
-7. KVM_SEV_DBG_DECRYPT
-----------------------
-
-The KVM_SEV_DEBUG_DECRYPT command can be used by the hypervisor to request the
-firmware to decrypt the data at the given memory region.
-
-Parameters (in): struct kvm_sev_dbg
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_dbg {
-                __u64 src_uaddr;        /* userspace address of data to decrypt */
-                __u64 dst_uaddr;        /* userspace address of destination */
-                __u32 len;              /* length of memory region to decrypt */
-        };
-
-The command returns an error if the guest policy does not allow debugging.
-
-8. KVM_SEV_DBG_ENCRYPT
-----------------------
-
-The KVM_SEV_DEBUG_ENCRYPT command can be used by the hypervisor to request the
-firmware to encrypt the data at the given memory region.
-
-Parameters (in): struct kvm_sev_dbg
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_dbg {
-                __u64 src_uaddr;        /* userspace address of data to encrypt */
-                __u64 dst_uaddr;        /* userspace address of destination */
-                __u32 len;              /* length of memory region to encrypt */
-        };
-
-The command returns an error if the guest policy does not allow debugging.
-
-9. KVM_SEV_LAUNCH_SECRET
-------------------------
-
-The KVM_SEV_LAUNCH_SECRET command can be used by the hypervisor to inject secret
-data after the measurement has been validated by the guest owner.
-
-Parameters (in): struct kvm_sev_launch_secret
-
-Returns: 0 on success, -negative on error
-
-::
-
-        struct kvm_sev_launch_secret {
-                __u64 hdr_uaddr;        /* userspace address containing the packet header */
-                __u32 hdr_len;
-
-                __u64 guest_uaddr;      /* the guest memory region where the secret should be injected */
-                __u32 guest_len;
-
-                __u64 trans_uaddr;      /* the hypervisor memory region which contains the secret */
-                __u32 trans_len;
-        };
-
-References
-==========
-
-
-See [white-paper]_, [api-spec]_, [amd-apm]_ and [kvm-forum]_ for more info.
-
-.. [white-paper] http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
-.. [api-spec] http://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
-.. [amd-apm] http://support.amd.com/TechDocs/24593.pdf (section 15.34)
-.. [kvm-forum]  http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
deleted file mode 100644 (file)
index e54a3f5..0000000
+++ /dev/null
@@ -1,5296 +0,0 @@
-The Definitive KVM (Kernel-based Virtual Machine) API Documentation
-===================================================================
-
-1. General description
-----------------------
-
-The kvm API is a set of ioctls that are issued to control various aspects
-of a virtual machine.  The ioctls belong to three classes:
-
- - System ioctls: These query and set global attributes which affect the
-   whole kvm subsystem.  In addition a system ioctl is used to create
-   virtual machines.
-
- - VM ioctls: These query and set attributes that affect an entire virtual
-   machine, for example memory layout.  In addition a VM ioctl is used to
-   create virtual cpus (vcpus) and devices.
-
-   VM ioctls must be issued from the same process (address space) that was
-   used to create the VM.
-
- - vcpu ioctls: These query and set attributes that control the operation
-   of a single virtual cpu.
-
-   vcpu ioctls should be issued from the same thread that was used to create
-   the vcpu, except for asynchronous vcpu ioctl that are marked as such in
-   the documentation.  Otherwise, the first ioctl after switching threads
-   could see a performance impact.
-
- - device ioctls: These query and set attributes that control the operation
-   of a single device.
-
-   device ioctls must be issued from the same process (address space) that
-   was used to create the VM.
-
-2. File descriptors
--------------------
-
-The kvm API is centered around file descriptors.  An initial
-open("/dev/kvm") obtains a handle to the kvm subsystem; this handle
-can be used to issue system ioctls.  A KVM_CREATE_VM ioctl on this
-handle will create a VM file descriptor which can be used to issue VM
-ioctls.  A KVM_CREATE_VCPU or KVM_CREATE_DEVICE ioctl on a VM fd will
-create a virtual cpu or device and return a file descriptor pointing to
-the new resource.  Finally, ioctls on a vcpu or device fd can be used
-to control the vcpu or device.  For vcpus, this includes the important
-task of actually running guest code.
-
-In general file descriptors can be migrated among processes by means
-of fork() and the SCM_RIGHTS facility of unix domain socket.  These
-kinds of tricks are explicitly not supported by kvm.  While they will
-not cause harm to the host, their actual behavior is not guaranteed by
-the API.  See "General description" for details on the ioctl usage
-model that is supported by KVM.
-
-It is important to note that althought VM ioctls may only be issued from
-the process that created the VM, a VM's lifecycle is associated with its
-file descriptor, not its creator (process).  In other words, the VM and
-its resources, *including the associated address space*, are not freed
-until the last reference to the VM's file descriptor has been released.
-For example, if fork() is issued after ioctl(KVM_CREATE_VM), the VM will
-not be freed until both the parent (original) process and its child have
-put their references to the VM's file descriptor.
-
-Because a VM's resources are not freed until the last reference to its
-file descriptor is released, creating additional references to a VM via
-via fork(), dup(), etc... without careful consideration is strongly
-discouraged and may have unwanted side effects, e.g. memory allocated
-by and on behalf of the VM's process may not be freed/unaccounted when
-the VM is shut down.
-
-
-3. Extensions
--------------
-
-As of Linux 2.6.22, the KVM ABI has been stabilized: no backward
-incompatible change are allowed.  However, there is an extension
-facility that allows backward-compatible extensions to the API to be
-queried and used.
-
-The extension mechanism is not based on the Linux version number.
-Instead, kvm defines extension identifiers and a facility to query
-whether a particular extension identifier is available.  If it is, a
-set of ioctls is available for application use.
-
-
-4. API description
-------------------
-
-This section describes ioctls that can be used to control kvm guests.
-For each ioctl, the following information is provided along with a
-description:
-
-  Capability: which KVM extension provides this ioctl.  Can be 'basic',
-      which means that is will be provided by any kernel that supports
-      API version 12 (see section 4.1), a KVM_CAP_xyz constant, which
-      means availability needs to be checked with KVM_CHECK_EXTENSION
-      (see section 4.4), or 'none' which means that while not all kernels
-      support this ioctl, there's no capability bit to check its
-      availability: for kernels that don't support the ioctl,
-      the ioctl returns -ENOTTY.
-
-  Architectures: which instruction set architectures provide this ioctl.
-      x86 includes both i386 and x86_64.
-
-  Type: system, vm, or vcpu.
-
-  Parameters: what parameters are accepted by the ioctl.
-
-  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
-      are not detailed, but errors with specific meanings are.
-
-
-4.1 KVM_GET_API_VERSION
-
-Capability: basic
-Architectures: all
-Type: system ioctl
-Parameters: none
-Returns: the constant KVM_API_VERSION (=12)
-
-This identifies the API version as the stable kvm API. It is not
-expected that this number will change.  However, Linux 2.6.20 and
-2.6.21 report earlier versions; these are not documented and not
-supported.  Applications should refuse to run if KVM_GET_API_VERSION
-returns a value other than 12.  If this check passes, all ioctls
-described as 'basic' will be available.
-
-
-4.2 KVM_CREATE_VM
-
-Capability: basic
-Architectures: all
-Type: system ioctl
-Parameters: machine type identifier (KVM_VM_*)
-Returns: a VM fd that can be used to control the new virtual machine.
-
-The new VM has no virtual cpus and no memory.
-You probably want to use 0 as machine type.
-
-In order to create user controlled virtual machines on S390, check
-KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
-privileged user (CAP_SYS_ADMIN).
-
-To use hardware assisted virtualization on MIPS (VZ ASE) rather than
-the default trap & emulate implementation (which changes the virtual
-memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
-flag KVM_VM_MIPS_VZ.
-
-
-On arm64, the physical address size for a VM (IPA Size limit) is limited
-to 40bits by default. The limit can be configured if the host supports the
-extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
-KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) to set the size in the machine type
-identifier, where IPA_Bits is the maximum width of any physical
-address used by the VM. The IPA_Bits is encoded in bits[7-0] of the
-machine type identifier.
-
-e.g, to configure a guest to use 48bit physical address size :
-
-    vm_fd = ioctl(dev_fd, KVM_CREATE_VM, KVM_VM_TYPE_ARM_IPA_SIZE(48));
-
-The requested size (IPA_Bits) must be :
-  0 - Implies default size, 40bits (for backward compatibility)
-
-  or
-
-  N - Implies N bits, where N is a positive integer such that,
-      32 <= N <= Host_IPA_Limit
-
-Host_IPA_Limit is the maximum possible value for IPA_Bits on the host and
-is dependent on the CPU capability and the kernel configuration. The limit can
-be retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the KVM_CHECK_EXTENSION
-ioctl() at run-time.
-
-Please note that configuring the IPA size does not affect the capability
-exposed by the guest CPUs in ID_AA64MMFR0_EL1[PARange]. It only affects
-size of the address translated by the stage2 level (guest physical to
-host physical address translations).
-
-
-4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
-
-Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
-Architectures: x86
-Type: system ioctl
-Parameters: struct kvm_msr_list (in/out)
-Returns: 0 on success; -1 on error
-Errors:
-  EFAULT:    the msr index list cannot be read from or written to
-  E2BIG:     the msr index list is to be to fit in the array specified by
-             the user.
-
-struct kvm_msr_list {
-       __u32 nmsrs; /* number of msrs in entries */
-       __u32 indices[0];
-};
-
-The user fills in the size of the indices array in nmsrs, and in return
-kvm adjusts nmsrs to reflect the actual number of msrs and fills in the
-indices array with their numbers.
-
-KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported.  The list
-varies by kvm version and host processor, but does not change otherwise.
-
-Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
-not returned in the MSR list, as different vcpus can have a different number
-of banks, as set via the KVM_X86_SETUP_MCE ioctl.
-
-KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed
-to the KVM_GET_MSRS system ioctl.  This lets userspace probe host capabilities
-and processor features that are exposed via MSRs (e.g., VMX capabilities).
-This list also varies by kvm version and host processor, but does not change
-otherwise.
-
-
-4.4 KVM_CHECK_EXTENSION
-
-Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
-Architectures: all
-Type: system ioctl, vm ioctl
-Parameters: extension identifier (KVM_CAP_*)
-Returns: 0 if unsupported; 1 (or some other positive integer) if supported
-
-The API allows the application to query about extensions to the core
-kvm API.  Userspace passes an extension identifier (an integer) and
-receives an integer that describes the extension availability.
-Generally 0 means no and 1 means yes, but some extensions may report
-additional information in the integer return value.
-
-Based on their initialization different VMs may have different capabilities.
-It is thus encouraged to use the vm ioctl to query for capabilities (available
-with KVM_CAP_CHECK_EXTENSION_VM on the vm fd)
-
-4.5 KVM_GET_VCPU_MMAP_SIZE
-
-Capability: basic
-Architectures: all
-Type: system ioctl
-Parameters: none
-Returns: size of vcpu mmap area, in bytes
-
-The KVM_RUN ioctl (cf.) communicates with userspace via a shared
-memory region.  This ioctl returns the size of that region.  See the
-KVM_RUN documentation for details.
-
-
-4.6 KVM_SET_MEMORY_REGION
-
-Capability: basic
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_memory_region (in)
-Returns: 0 on success, -1 on error
-
-This ioctl is obsolete and has been removed.
-
-
-4.7 KVM_CREATE_VCPU
-
-Capability: basic
-Architectures: all
-Type: vm ioctl
-Parameters: vcpu id (apic id on x86)
-Returns: vcpu fd on success, -1 on error
-
-This API adds a vcpu to a virtual machine. No more than max_vcpus may be added.
-The vcpu id is an integer in the range [0, max_vcpu_id).
-
-The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
-the KVM_CHECK_EXTENSION ioctl() at run-time.
-The maximum possible value for max_vcpus can be retrieved using the
-KVM_CAP_MAX_VCPUS of the KVM_CHECK_EXTENSION ioctl() at run-time.
-
-If the KVM_CAP_NR_VCPUS does not exist, you should assume that max_vcpus is 4
-cpus max.
-If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
-same as the value returned from KVM_CAP_NR_VCPUS.
-
-The maximum possible value for max_vcpu_id can be retrieved using the
-KVM_CAP_MAX_VCPU_ID of the KVM_CHECK_EXTENSION ioctl() at run-time.
-
-If the KVM_CAP_MAX_VCPU_ID does not exist, you should assume that max_vcpu_id
-is the same as the value returned from KVM_CAP_MAX_VCPUS.
-
-On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
-threads in one or more virtual CPU cores.  (This is because the
-hardware requires all the hardware threads in a CPU core to be in the
-same partition.)  The KVM_CAP_PPC_SMT capability indicates the number
-of vcpus per virtual core (vcore).  The vcore id is obtained by
-dividing the vcpu id by the number of vcpus per vcore.  The vcpus in a
-given vcore will always be in the same physical core as each other
-(though that might be a different physical core from time to time).
-Userspace can control the threading (SMT) mode of the guest by its
-allocation of vcpu ids.  For example, if userspace wants
-single-threaded guest vcpus, it should make all vcpu ids be a multiple
-of the number of vcpus per vcore.
-
-For virtual cpus that have been created with S390 user controlled virtual
-machines, the resulting vcpu fd can be memory mapped at page offset
-KVM_S390_SIE_PAGE_OFFSET in order to obtain a memory map of the virtual
-cpu's hardware control block.
-
-
-4.8 KVM_GET_DIRTY_LOG (vm ioctl)
-
-Capability: basic
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_dirty_log (in/out)
-Returns: 0 on success, -1 on error
-
-/* for KVM_GET_DIRTY_LOG */
-struct kvm_dirty_log {
-       __u32 slot;
-       __u32 padding;
-       union {
-               void __user *dirty_bitmap; /* one bit per page */
-               __u64 padding;
-       };
-};
-
-Given a memory slot, return a bitmap containing any pages dirtied
-since the last call to this ioctl.  Bit 0 is the first page in the
-memory slot.  Ensure the entire structure is cleared to avoid padding
-issues.
-
-If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
-the address space for which you want to return the dirty bitmap.
-They must be less than the value that KVM_CHECK_EXTENSION returns for
-the KVM_CAP_MULTI_ADDRESS_SPACE capability.
-
-The bits in the dirty bitmap are cleared before the ioctl returns, unless
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is enabled.  For more information,
-see the description of the capability.
-
-4.9 KVM_SET_MEMORY_ALIAS
-
-Capability: basic
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_memory_alias (in)
-Returns: 0 (success), -1 (error)
-
-This ioctl is obsolete and has been removed.
-
-
-4.10 KVM_RUN
-
-Capability: basic
-Architectures: all
-Type: vcpu ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-Errors:
-  EINTR:     an unmasked signal is pending
-
-This ioctl is used to run a guest virtual cpu.  While there are no
-explicit parameters, there is an implicit parameter block that can be
-obtained by mmap()ing the vcpu fd at offset 0, with the size given by
-KVM_GET_VCPU_MMAP_SIZE.  The parameter block is formatted as a 'struct
-kvm_run' (see below).
-
-
-4.11 KVM_GET_REGS
-
-Capability: basic
-Architectures: all except ARM, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_regs (out)
-Returns: 0 on success, -1 on error
-
-Reads the general purpose registers from the vcpu.
-
-/* x86 */
-struct kvm_regs {
-       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
-       __u64 rax, rbx, rcx, rdx;
-       __u64 rsi, rdi, rsp, rbp;
-       __u64 r8,  r9,  r10, r11;
-       __u64 r12, r13, r14, r15;
-       __u64 rip, rflags;
-};
-
-/* mips */
-struct kvm_regs {
-       /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
-       __u64 gpr[32];
-       __u64 hi;
-       __u64 lo;
-       __u64 pc;
-};
-
-
-4.12 KVM_SET_REGS
-
-Capability: basic
-Architectures: all except ARM, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_regs (in)
-Returns: 0 on success, -1 on error
-
-Writes the general purpose registers into the vcpu.
-
-See KVM_GET_REGS for the data structure.
-
-
-4.13 KVM_GET_SREGS
-
-Capability: basic
-Architectures: x86, ppc
-Type: vcpu ioctl
-Parameters: struct kvm_sregs (out)
-Returns: 0 on success, -1 on error
-
-Reads special registers from the vcpu.
-
-/* x86 */
-struct kvm_sregs {
-       struct kvm_segment cs, ds, es, fs, gs, ss;
-       struct kvm_segment tr, ldt;
-       struct kvm_dtable gdt, idt;
-       __u64 cr0, cr2, cr3, cr4, cr8;
-       __u64 efer;
-       __u64 apic_base;
-       __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
-};
-
-/* ppc -- see arch/powerpc/include/uapi/asm/kvm.h */
-
-interrupt_bitmap is a bitmap of pending external interrupts.  At most
-one bit may be set.  This interrupt has been acknowledged by the APIC
-but not yet injected into the cpu core.
-
-
-4.14 KVM_SET_SREGS
-
-Capability: basic
-Architectures: x86, ppc
-Type: vcpu ioctl
-Parameters: struct kvm_sregs (in)
-Returns: 0 on success, -1 on error
-
-Writes special registers into the vcpu.  See KVM_GET_SREGS for the
-data structures.
-
-
-4.15 KVM_TRANSLATE
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_translation (in/out)
-Returns: 0 on success, -1 on error
-
-Translates a virtual address according to the vcpu's current address
-translation mode.
-
-struct kvm_translation {
-       /* in */
-       __u64 linear_address;
-
-       /* out */
-       __u64 physical_address;
-       __u8  valid;
-       __u8  writeable;
-       __u8  usermode;
-       __u8  pad[5];
-};
-
-
-4.16 KVM_INTERRUPT
-
-Capability: basic
-Architectures: x86, ppc, mips
-Type: vcpu ioctl
-Parameters: struct kvm_interrupt (in)
-Returns: 0 on success, negative on failure.
-
-Queues a hardware interrupt vector to be injected.
-
-/* for KVM_INTERRUPT */
-struct kvm_interrupt {
-       /* in */
-       __u32 irq;
-};
-
-X86:
-
-Returns: 0 on success,
-        -EEXIST if an interrupt is already enqueued
-        -EINVAL the the irq number is invalid
-        -ENXIO if the PIC is in the kernel
-        -EFAULT if the pointer is invalid
-
-Note 'irq' is an interrupt vector, not an interrupt pin or line. This
-ioctl is useful if the in-kernel PIC is not used.
-
-PPC:
-
-Queues an external interrupt to be injected. This ioctl is overleaded
-with 3 different irq values:
-
-a) KVM_INTERRUPT_SET
-
-  This injects an edge type external interrupt into the guest once it's ready
-  to receive interrupts. When injected, the interrupt is done.
-
-b) KVM_INTERRUPT_UNSET
-
-  This unsets any pending interrupt.
-
-  Only available with KVM_CAP_PPC_UNSET_IRQ.
-
-c) KVM_INTERRUPT_SET_LEVEL
-
-  This injects a level type external interrupt into the guest context. The
-  interrupt stays pending until a specific ioctl with KVM_INTERRUPT_UNSET
-  is triggered.
-
-  Only available with KVM_CAP_PPC_IRQ_LEVEL.
-
-Note that any value for 'irq' other than the ones stated above is invalid
-and incurs unexpected behavior.
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-MIPS:
-
-Queues an external interrupt to be injected into the virtual CPU. A negative
-interrupt number dequeues the interrupt.
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-
-4.17 KVM_DEBUG_GUEST
-
-Capability: basic
-Architectures: none
-Type: vcpu ioctl
-Parameters: none)
-Returns: -1 on error
-
-Support for this has been removed.  Use KVM_SET_GUEST_DEBUG instead.
-
-
-4.18 KVM_GET_MSRS
-
-Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
-Architectures: x86
-Type: system ioctl, vcpu ioctl
-Parameters: struct kvm_msrs (in/out)
-Returns: number of msrs successfully returned;
-        -1 on error
-
-When used as a system ioctl:
-Reads the values of MSR-based features that are available for the VM.  This
-is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values.
-The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST
-in a system ioctl.
-
-When used as a vcpu ioctl:
-Reads model-specific registers from the vcpu.  Supported msr indices can
-be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
-
-struct kvm_msrs {
-       __u32 nmsrs; /* number of msrs in entries */
-       __u32 pad;
-
-       struct kvm_msr_entry entries[0];
-};
-
-struct kvm_msr_entry {
-       __u32 index;
-       __u32 reserved;
-       __u64 data;
-};
-
-Application code should set the 'nmsrs' member (which indicates the
-size of the entries array) and the 'index' member of each array entry.
-kvm will fill in the 'data' member.
-
-
-4.19 KVM_SET_MSRS
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_msrs (in)
-Returns: 0 on success, -1 on error
-
-Writes model-specific registers to the vcpu.  See KVM_GET_MSRS for the
-data structures.
-
-Application code should set the 'nmsrs' member (which indicates the
-size of the entries array), and the 'index' and 'data' members of each
-array entry.
-
-
-4.20 KVM_SET_CPUID
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_cpuid (in)
-Returns: 0 on success, -1 on error
-
-Defines the vcpu responses to the cpuid instruction.  Applications
-should use the KVM_SET_CPUID2 ioctl if available.
-
-
-struct kvm_cpuid_entry {
-       __u32 function;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding;
-};
-
-/* for KVM_SET_CPUID */
-struct kvm_cpuid {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry entries[0];
-};
-
-
-4.21 KVM_SET_SIGNAL_MASK
-
-Capability: basic
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_signal_mask (in)
-Returns: 0 on success, -1 on error
-
-Defines which signals are blocked during execution of KVM_RUN.  This
-signal mask temporarily overrides the threads signal mask.  Any
-unblocked signal received (except SIGKILL and SIGSTOP, which retain
-their traditional behaviour) will cause KVM_RUN to return with -EINTR.
-
-Note the signal will only be delivered if not blocked by the original
-signal mask.
-
-/* for KVM_SET_SIGNAL_MASK */
-struct kvm_signal_mask {
-       __u32 len;
-       __u8  sigset[0];
-};
-
-
-4.22 KVM_GET_FPU
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_fpu (out)
-Returns: 0 on success, -1 on error
-
-Reads the floating point state from the vcpu.
-
-/* for KVM_GET_FPU and KVM_SET_FPU */
-struct kvm_fpu {
-       __u8  fpr[8][16];
-       __u16 fcw;
-       __u16 fsw;
-       __u8  ftwx;  /* in fxsave format */
-       __u8  pad1;
-       __u16 last_opcode;
-       __u64 last_ip;
-       __u64 last_dp;
-       __u8  xmm[16][16];
-       __u32 mxcsr;
-       __u32 pad2;
-};
-
-
-4.23 KVM_SET_FPU
-
-Capability: basic
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_fpu (in)
-Returns: 0 on success, -1 on error
-
-Writes the floating point state to the vcpu.
-
-/* for KVM_GET_FPU and KVM_SET_FPU */
-struct kvm_fpu {
-       __u8  fpr[8][16];
-       __u16 fcw;
-       __u16 fsw;
-       __u8  ftwx;  /* in fxsave format */
-       __u8  pad1;
-       __u16 last_opcode;
-       __u64 last_ip;
-       __u64 last_dp;
-       __u8  xmm[16][16];
-       __u32 mxcsr;
-       __u32 pad2;
-};
-
-
-4.24 KVM_CREATE_IRQCHIP
-
-Capability: KVM_CAP_IRQCHIP, KVM_CAP_S390_IRQCHIP (s390)
-Architectures: x86, ARM, arm64, s390
-Type: vm ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-
-Creates an interrupt controller model in the kernel.
-On x86, creates a virtual ioapic, a virtual PIC (two PICs, nested), and sets up
-future vcpus to have a local APIC.  IRQ routing for GSIs 0-15 is set to both
-PIC and IOAPIC; GSI 16-23 only go to the IOAPIC.
-On ARM/arm64, a GICv2 is created. Any other GIC versions require the usage of
-KVM_CREATE_DEVICE, which also supports creating a GICv2.  Using
-KVM_CREATE_DEVICE is preferred over KVM_CREATE_IRQCHIP for GICv2.
-On s390, a dummy irq routing table is created.
-
-Note that on s390 the KVM_CAP_S390_IRQCHIP vm capability needs to be enabled
-before KVM_CREATE_IRQCHIP can be used.
-
-
-4.25 KVM_IRQ_LINE
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86, arm, arm64
-Type: vm ioctl
-Parameters: struct kvm_irq_level
-Returns: 0 on success, -1 on error
-
-Sets the level of a GSI input to the interrupt controller model in the kernel.
-On some architectures it is required that an interrupt controller model has
-been previously created with KVM_CREATE_IRQCHIP.  Note that edge-triggered
-interrupts require the level to be set to 1 and then back to 0.
-
-On real hardware, interrupt pins can be active-low or active-high.  This
-does not matter for the level field of struct kvm_irq_level: 1 always
-means active (asserted), 0 means inactive (deasserted).
-
-x86 allows the operating system to program the interrupt polarity
-(active-low/active-high) for level-triggered interrupts, and KVM used
-to consider the polarity.  However, due to bitrot in the handling of
-active-low interrupts, the above convention is now valid on x86 too.
-This is signaled by KVM_CAP_X86_IOAPIC_POLARITY_IGNORED.  Userspace
-should not present interrupts to the guest as active-low unless this
-capability is present (or unless it is not using the in-kernel irqchip,
-of course).
-
-
-ARM/arm64 can signal an interrupt either at the CPU level, or at the
-in-kernel irqchip (GIC), and for in-kernel irqchip can tell the GIC to
-use PPIs designated for specific cpus.  The irq field is interpreted
-like this:
-
-  bits:  | 31 ... 24 | 23  ... 16 | 15    ...    0 |
-  field: | irq_type  | vcpu_index |     irq_id     |
-
-The irq_type field has the following values:
-- irq_type[0]: out-of-kernel GIC: irq_id 0 is IRQ, irq_id 1 is FIQ
-- irq_type[1]: in-kernel GIC: SPI, irq_id between 32 and 1019 (incl.)
-               (the vcpu_index field is ignored)
-- irq_type[2]: in-kernel GIC: PPI, irq_id between 16 and 31 (incl.)
-
-(The irq_id field thus corresponds nicely to the IRQ ID in the ARM GIC specs)
-
-In both cases, level is used to assert/deassert the line.
-
-struct kvm_irq_level {
-       union {
-               __u32 irq;     /* GSI */
-               __s32 status;  /* not used for KVM_IRQ_LEVEL */
-       };
-       __u32 level;           /* 0 or 1 */
-};
-
-
-4.26 KVM_GET_IRQCHIP
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_irqchip (in/out)
-Returns: 0 on success, -1 on error
-
-Reads the state of a kernel interrupt controller created with
-KVM_CREATE_IRQCHIP into a buffer provided by the caller.
-
-struct kvm_irqchip {
-       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
-       __u32 pad;
-        union {
-               char dummy[512];  /* reserving space */
-               struct kvm_pic_state pic;
-               struct kvm_ioapic_state ioapic;
-       } chip;
-};
-
-
-4.27 KVM_SET_IRQCHIP
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_irqchip (in)
-Returns: 0 on success, -1 on error
-
-Sets the state of a kernel interrupt controller created with
-KVM_CREATE_IRQCHIP from a buffer provided by the caller.
-
-struct kvm_irqchip {
-       __u32 chip_id;  /* 0 = PIC1, 1 = PIC2, 2 = IOAPIC */
-       __u32 pad;
-        union {
-               char dummy[512];  /* reserving space */
-               struct kvm_pic_state pic;
-               struct kvm_ioapic_state ioapic;
-       } chip;
-};
-
-
-4.28 KVM_XEN_HVM_CONFIG
-
-Capability: KVM_CAP_XEN_HVM
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_xen_hvm_config (in)
-Returns: 0 on success, -1 on error
-
-Sets the MSR that the Xen HVM guest uses to initialize its hypercall
-page, and provides the starting address and size of the hypercall
-blobs in userspace.  When the guest writes the MSR, kvm copies one
-page of a blob (32- or 64-bit, depending on the vcpu mode) to guest
-memory.
-
-struct kvm_xen_hvm_config {
-       __u32 flags;
-       __u32 msr;
-       __u64 blob_addr_32;
-       __u64 blob_addr_64;
-       __u8 blob_size_32;
-       __u8 blob_size_64;
-       __u8 pad2[30];
-};
-
-
-4.29 KVM_GET_CLOCK
-
-Capability: KVM_CAP_ADJUST_CLOCK
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_clock_data (out)
-Returns: 0 on success, -1 on error
-
-Gets the current timestamp of kvmclock as seen by the current guest. In
-conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios
-such as migration.
-
-When KVM_CAP_ADJUST_CLOCK is passed to KVM_CHECK_EXTENSION, it returns the
-set of bits that KVM can return in struct kvm_clock_data's flag member.
-
-The only flag defined now is KVM_CLOCK_TSC_STABLE.  If set, the returned
-value is the exact kvmclock value seen by all VCPUs at the instant
-when KVM_GET_CLOCK was called.  If clear, the returned value is simply
-CLOCK_MONOTONIC plus a constant offset; the offset can be modified
-with KVM_SET_CLOCK.  KVM will try to make all VCPUs follow this clock,
-but the exact value read by each VCPU could differ, because the host
-TSC is not stable.
-
-struct kvm_clock_data {
-       __u64 clock;  /* kvmclock current value */
-       __u32 flags;
-       __u32 pad[9];
-};
-
-
-4.30 KVM_SET_CLOCK
-
-Capability: KVM_CAP_ADJUST_CLOCK
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_clock_data (in)
-Returns: 0 on success, -1 on error
-
-Sets the current timestamp of kvmclock to the value specified in its parameter.
-In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios
-such as migration.
-
-struct kvm_clock_data {
-       __u64 clock;  /* kvmclock current value */
-       __u32 flags;
-       __u32 pad[9];
-};
-
-
-4.31 KVM_GET_VCPU_EVENTS
-
-Capability: KVM_CAP_VCPU_EVENTS
-Extended by: KVM_CAP_INTR_SHADOW
-Architectures: x86, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_vcpu_event (out)
-Returns: 0 on success, -1 on error
-
-X86:
-
-Gets currently pending exceptions, interrupts, and NMIs as well as related
-states of the vcpu.
-
-struct kvm_vcpu_events {
-       struct {
-               __u8 injected;
-               __u8 nr;
-               __u8 has_error_code;
-               __u8 pending;
-               __u32 error_code;
-       } exception;
-       struct {
-               __u8 injected;
-               __u8 nr;
-               __u8 soft;
-               __u8 shadow;
-       } interrupt;
-       struct {
-               __u8 injected;
-               __u8 pending;
-               __u8 masked;
-               __u8 pad;
-       } nmi;
-       __u32 sipi_vector;
-       __u32 flags;
-       struct {
-               __u8 smm;
-               __u8 pending;
-               __u8 smm_inside_nmi;
-               __u8 latched_init;
-       } smi;
-       __u8 reserved[27];
-       __u8 exception_has_payload;
-       __u64 exception_payload;
-};
-
-The following bits are defined in the flags field:
-
-- KVM_VCPUEVENT_VALID_SHADOW may be set to signal that
-  interrupt.shadow contains a valid state.
-
-- KVM_VCPUEVENT_VALID_SMM may be set to signal that smi contains a
-  valid state.
-
-- KVM_VCPUEVENT_VALID_PAYLOAD may be set to signal that the
-  exception_has_payload, exception_payload, and exception.pending
-  fields contain a valid state. This bit will be set whenever
-  KVM_CAP_EXCEPTION_PAYLOAD is enabled.
-
-ARM/ARM64:
-
-If the guest accesses a device that is being emulated by the host kernel in
-such a way that a real device would generate a physical SError, KVM may make
-a virtual SError pending for that VCPU. This system error interrupt remains
-pending until the guest takes the exception by unmasking PSTATE.A.
-
-Running the VCPU may cause it to take a pending SError, or make an access that
-causes an SError to become pending. The event's description is only valid while
-the VPCU is not running.
-
-This API provides a way to read and write the pending 'event' state that is not
-visible to the guest. To save, restore or migrate a VCPU the struct representing
-the state can be read then written using this GET/SET API, along with the other
-guest-visible registers. It is not possible to 'cancel' an SError that has been
-made pending.
-
-A device being emulated in user-space may also wish to generate an SError. To do
-this the events structure can be populated by user-space. The current state
-should be read first, to ensure no existing SError is pending. If an existing
-SError is pending, the architecture's 'Multiple SError interrupts' rules should
-be followed. (2.5.3 of DDI0587.a "ARM Reliability, Availability, and
-Serviceability (RAS) Specification").
-
-SError exceptions always have an ESR value. Some CPUs have the ability to
-specify what the virtual SError's ESR value should be. These systems will
-advertise KVM_CAP_ARM_INJECT_SERROR_ESR. In this case exception.has_esr will
-always have a non-zero value when read, and the agent making an SError pending
-should specify the ISS field in the lower 24 bits of exception.serror_esr. If
-the system supports KVM_CAP_ARM_INJECT_SERROR_ESR, but user-space sets the events
-with exception.has_esr as zero, KVM will choose an ESR.
-
-Specifying exception.has_esr on a system that does not support it will return
--EINVAL. Setting anything other than the lower 24bits of exception.serror_esr
-will return -EINVAL.
-
-struct kvm_vcpu_events {
-       struct {
-               __u8 serror_pending;
-               __u8 serror_has_esr;
-               /* Align it to 8 bytes */
-               __u8 pad[6];
-               __u64 serror_esr;
-       } exception;
-       __u32 reserved[12];
-};
-
-4.32 KVM_SET_VCPU_EVENTS
-
-Capability: KVM_CAP_VCPU_EVENTS
-Extended by: KVM_CAP_INTR_SHADOW
-Architectures: x86, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_vcpu_event (in)
-Returns: 0 on success, -1 on error
-
-X86:
-
-Set pending exceptions, interrupts, and NMIs as well as related states of the
-vcpu.
-
-See KVM_GET_VCPU_EVENTS for the data structure.
-
-Fields that may be modified asynchronously by running VCPUs can be excluded
-from the update. These fields are nmi.pending, sipi_vector, smi.smm,
-smi.pending. Keep the corresponding bits in the flags field cleared to
-suppress overwriting the current in-kernel state. The bits are:
-
-KVM_VCPUEVENT_VALID_NMI_PENDING - transfer nmi.pending to the kernel
-KVM_VCPUEVENT_VALID_SIPI_VECTOR - transfer sipi_vector
-KVM_VCPUEVENT_VALID_SMM         - transfer the smi sub-struct.
-
-If KVM_CAP_INTR_SHADOW is available, KVM_VCPUEVENT_VALID_SHADOW can be set in
-the flags field to signal that interrupt.shadow contains a valid state and
-shall be written into the VCPU.
-
-KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available.
-
-If KVM_CAP_EXCEPTION_PAYLOAD is enabled, KVM_VCPUEVENT_VALID_PAYLOAD
-can be set in the flags field to signal that the
-exception_has_payload, exception_payload, and exception.pending fields
-contain a valid state and shall be written into the VCPU.
-
-ARM/ARM64:
-
-Set the pending SError exception state for this VCPU. It is not possible to
-'cancel' an Serror that has been made pending.
-
-See KVM_GET_VCPU_EVENTS for the data structure.
-
-
-4.33 KVM_GET_DEBUGREGS
-
-Capability: KVM_CAP_DEBUGREGS
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_debugregs (out)
-Returns: 0 on success, -1 on error
-
-Reads debug registers from the vcpu.
-
-struct kvm_debugregs {
-       __u64 db[4];
-       __u64 dr6;
-       __u64 dr7;
-       __u64 flags;
-       __u64 reserved[9];
-};
-
-
-4.34 KVM_SET_DEBUGREGS
-
-Capability: KVM_CAP_DEBUGREGS
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_debugregs (in)
-Returns: 0 on success, -1 on error
-
-Writes debug registers into the vcpu.
-
-See KVM_GET_DEBUGREGS for the data structure. The flags field is unused
-yet and must be cleared on entry.
-
-
-4.35 KVM_SET_USER_MEMORY_REGION
-
-Capability: KVM_CAP_USER_MEMORY
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_userspace_memory_region (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_userspace_memory_region {
-       __u32 slot;
-       __u32 flags;
-       __u64 guest_phys_addr;
-       __u64 memory_size; /* bytes */
-       __u64 userspace_addr; /* start of the userspace allocated memory */
-};
-
-/* for kvm_memory_region::flags */
-#define KVM_MEM_LOG_DIRTY_PAGES        (1UL << 0)
-#define KVM_MEM_READONLY       (1UL << 1)
-
-This ioctl allows the user to create, modify or delete a guest physical
-memory slot.  Bits 0-15 of "slot" specify the slot id and this value
-should be less than the maximum number of user memory slots supported per
-VM.  The maximum allowed slots can be queried using KVM_CAP_NR_MEMSLOTS.
-Slots may not overlap in guest physical address space.
-
-If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 of "slot"
-specifies the address space which is being modified.  They must be
-less than the value that KVM_CHECK_EXTENSION returns for the
-KVM_CAP_MULTI_ADDRESS_SPACE capability.  Slots in separate address spaces
-are unrelated; the restriction on overlapping slots only applies within
-each address space.
-
-Deleting a slot is done by passing zero for memory_size.  When changing
-an existing slot, it may be moved in the guest physical memory space,
-or its flags may be modified, but it may not be resized.
-
-Memory for the region is taken starting at the address denoted by the
-field userspace_addr, which must point at user addressable memory for
-the entire memory slot size.  Any object may back this memory, including
-anonymous memory, ordinary files, and hugetlbfs.
-
-It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
-be identical.  This allows large pages in the guest to be backed by large
-pages in the host.
-
-The flags field supports two flags: KVM_MEM_LOG_DIRTY_PAGES and
-KVM_MEM_READONLY.  The former can be set to instruct KVM to keep track of
-writes to memory within the slot.  See KVM_GET_DIRTY_LOG ioctl to know how to
-use it.  The latter can be set, if KVM_CAP_READONLY_MEM capability allows it,
-to make a new slot read-only.  In this case, writes to this memory will be
-posted to userspace as KVM_EXIT_MMIO exits.
-
-When the KVM_CAP_SYNC_MMU capability is available, changes in the backing of
-the memory region are automatically reflected into the guest.  For example, an
-mmap() that affects the region will be made visible immediately.  Another
-example is madvise(MADV_DROP).
-
-It is recommended to use this API instead of the KVM_SET_MEMORY_REGION ioctl.
-The KVM_SET_MEMORY_REGION does not allow fine grained control over memory
-allocation and is deprecated.
-
-
-4.36 KVM_SET_TSS_ADDR
-
-Capability: KVM_CAP_SET_TSS_ADDR
-Architectures: x86
-Type: vm ioctl
-Parameters: unsigned long tss_address (in)
-Returns: 0 on success, -1 on error
-
-This ioctl defines the physical address of a three-page region in the guest
-physical address space.  The region must be within the first 4GB of the
-guest physical address space and must not conflict with any memory slot
-or any mmio address.  The guest may malfunction if it accesses this memory
-region.
-
-This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
-because of a quirk in the virtualization implementation (see the internals
-documentation when it pops into existence).
-
-
-4.37 KVM_ENABLE_CAP
-
-Capability: KVM_CAP_ENABLE_CAP
-Architectures: mips, ppc, s390
-Type: vcpu ioctl
-Parameters: struct kvm_enable_cap (in)
-Returns: 0 on success; -1 on error
-
-Capability: KVM_CAP_ENABLE_CAP_VM
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_enable_cap (in)
-Returns: 0 on success; -1 on error
-
-+Not all extensions are enabled by default. Using this ioctl the application
-can enable an extension, making it available to the guest.
-
-On systems that do not support this ioctl, it always fails. On systems that
-do support it, it only works for extensions that are supported for enablement.
-
-To check if a capability can be enabled, the KVM_CHECK_EXTENSION ioctl should
-be used.
-
-struct kvm_enable_cap {
-       /* in */
-       __u32 cap;
-
-The capability that is supposed to get enabled.
-
-       __u32 flags;
-
-A bitfield indicating future enhancements. Has to be 0 for now.
-
-       __u64 args[4];
-
-Arguments for enabling a feature. If a feature needs initial values to
-function properly, this is the place to put them.
-
-       __u8  pad[64];
-};
-
-The vcpu ioctl should be used for vcpu-specific capabilities, the vm ioctl
-for vm-wide capabilities.
-
-4.38 KVM_GET_MP_STATE
-
-Capability: KVM_CAP_MP_STATE
-Architectures: x86, s390, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_mp_state (out)
-Returns: 0 on success; -1 on error
-
-struct kvm_mp_state {
-       __u32 mp_state;
-};
-
-Returns the vcpu's current "multiprocessing state" (though also valid on
-uniprocessor guests).
-
-Possible values are:
-
- - KVM_MP_STATE_RUNNABLE:        the vcpu is currently running [x86,arm/arm64]
- - KVM_MP_STATE_UNINITIALIZED:   the vcpu is an application processor (AP)
-                                 which has not yet received an INIT signal [x86]
- - KVM_MP_STATE_INIT_RECEIVED:   the vcpu has received an INIT signal, and is
-                                 now ready for a SIPI [x86]
- - KVM_MP_STATE_HALTED:          the vcpu has executed a HLT instruction and
-                                 is waiting for an interrupt [x86]
- - KVM_MP_STATE_SIPI_RECEIVED:   the vcpu has just received a SIPI (vector
-                                 accessible via KVM_GET_VCPU_EVENTS) [x86]
- - KVM_MP_STATE_STOPPED:         the vcpu is stopped [s390,arm/arm64]
- - KVM_MP_STATE_CHECK_STOP:      the vcpu is in a special error state [s390]
- - KVM_MP_STATE_OPERATING:       the vcpu is operating (running or halted)
-                                 [s390]
- - KVM_MP_STATE_LOAD:            the vcpu is in a special load/startup state
-                                 [s390]
-
-On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
-in-kernel irqchip, the multiprocessing state must be maintained by userspace on
-these architectures.
-
-For arm/arm64:
-
-The only states that are valid are KVM_MP_STATE_STOPPED and
-KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.
-
-4.39 KVM_SET_MP_STATE
-
-Capability: KVM_CAP_MP_STATE
-Architectures: x86, s390, arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_mp_state (in)
-Returns: 0 on success; -1 on error
-
-Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for
-arguments.
-
-On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
-in-kernel irqchip, the multiprocessing state must be maintained by userspace on
-these architectures.
-
-For arm/arm64:
-
-The only states that are valid are KVM_MP_STATE_STOPPED and
-KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.
-
-4.40 KVM_SET_IDENTITY_MAP_ADDR
-
-Capability: KVM_CAP_SET_IDENTITY_MAP_ADDR
-Architectures: x86
-Type: vm ioctl
-Parameters: unsigned long identity (in)
-Returns: 0 on success, -1 on error
-
-This ioctl defines the physical address of a one-page region in the guest
-physical address space.  The region must be within the first 4GB of the
-guest physical address space and must not conflict with any memory slot
-or any mmio address.  The guest may malfunction if it accesses this memory
-region.
-
-Setting the address to 0 will result in resetting the address to its default
-(0xfffbc000).
-
-This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
-because of a quirk in the virtualization implementation (see the internals
-documentation when it pops into existence).
-
-Fails if any VCPU has already been created.
-
-4.41 KVM_SET_BOOT_CPU_ID
-
-Capability: KVM_CAP_SET_BOOT_CPU_ID
-Architectures: x86
-Type: vm ioctl
-Parameters: unsigned long vcpu_id
-Returns: 0 on success, -1 on error
-
-Define which vcpu is the Bootstrap Processor (BSP).  Values are the same
-as the vcpu id in KVM_CREATE_VCPU.  If this ioctl is not called, the default
-is vcpu 0.
-
-
-4.42 KVM_GET_XSAVE
-
-Capability: KVM_CAP_XSAVE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xsave (out)
-Returns: 0 on success, -1 on error
-
-struct kvm_xsave {
-       __u32 region[1024];
-};
-
-This ioctl would copy current vcpu's xsave struct to the userspace.
-
-
-4.43 KVM_SET_XSAVE
-
-Capability: KVM_CAP_XSAVE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xsave (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_xsave {
-       __u32 region[1024];
-};
-
-This ioctl would copy userspace's xsave struct to the kernel.
-
-
-4.44 KVM_GET_XCRS
-
-Capability: KVM_CAP_XCRS
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xcrs (out)
-Returns: 0 on success, -1 on error
-
-struct kvm_xcr {
-       __u32 xcr;
-       __u32 reserved;
-       __u64 value;
-};
-
-struct kvm_xcrs {
-       __u32 nr_xcrs;
-       __u32 flags;
-       struct kvm_xcr xcrs[KVM_MAX_XCRS];
-       __u64 padding[16];
-};
-
-This ioctl would copy current vcpu's xcrs to the userspace.
-
-
-4.45 KVM_SET_XCRS
-
-Capability: KVM_CAP_XCRS
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_xcrs (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_xcr {
-       __u32 xcr;
-       __u32 reserved;
-       __u64 value;
-};
-
-struct kvm_xcrs {
-       __u32 nr_xcrs;
-       __u32 flags;
-       struct kvm_xcr xcrs[KVM_MAX_XCRS];
-       __u64 padding[16];
-};
-
-This ioctl would set vcpu's xcr to the value userspace specified.
-
-
-4.46 KVM_GET_SUPPORTED_CPUID
-
-Capability: KVM_CAP_EXT_CPUID
-Architectures: x86
-Type: system ioctl
-Parameters: struct kvm_cpuid2 (in/out)
-Returns: 0 on success, -1 on error
-
-struct kvm_cpuid2 {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry2 entries[0];
-};
-
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
-#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
-#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
-
-struct kvm_cpuid_entry2 {
-       __u32 function;
-       __u32 index;
-       __u32 flags;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding[3];
-};
-
-This ioctl returns x86 cpuid features which are supported by both the
-hardware and kvm in its default configuration.  Userspace can use the
-information returned by this ioctl to construct cpuid information (for
-KVM_SET_CPUID2) that is consistent with hardware, kernel, and
-userspace capabilities, and with user requirements (for example, the
-user may wish to constrain cpuid to emulate older hardware, or for
-feature consistency across a cluster).
-
-Note that certain capabilities, such as KVM_CAP_X86_DISABLE_EXITS, may
-expose cpuid features (e.g. MONITOR) which are not supported by kvm in
-its default configuration. If userspace enables such capabilities, it
-is responsible for modifying the results of this ioctl appropriately.
-
-Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
-with the 'nent' field indicating the number of entries in the variable-size
-array 'entries'.  If the number of entries is too low to describe the cpu
-capabilities, an error (E2BIG) is returned.  If the number is too high,
-the 'nent' field is adjusted and an error (ENOMEM) is returned.  If the
-number is just right, the 'nent' field is adjusted to the number of valid
-entries in the 'entries' array, which is then filled.
-
-The entries returned are the host cpuid as returned by the cpuid instruction,
-with unknown or unsupported features masked out.  Some features (for example,
-x2apic), may not be present in the host cpu, but are exposed by kvm if it can
-emulate them efficiently. The fields in each entry are defined as follows:
-
-  function: the eax value used to obtain the entry
-  index: the ecx value used to obtain the entry (for entries that are
-         affected by ecx)
-  flags: an OR of zero or more of the following:
-        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
-           if the index field is valid
-        KVM_CPUID_FLAG_STATEFUL_FUNC:
-           if cpuid for this function returns different values for successive
-           invocations; there will be several entries with the same function,
-           all with this flag set
-        KVM_CPUID_FLAG_STATE_READ_NEXT:
-           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
-           the first entry to be read by a cpu
-   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
-         this function/index combination
-
-The TSC deadline timer feature (CPUID leaf 1, ecx[24]) is always returned
-as false, since the feature depends on KVM_CREATE_IRQCHIP for local APIC
-support.  Instead it is reported via
-
-  ioctl(KVM_CHECK_EXTENSION, KVM_CAP_TSC_DEADLINE_TIMER)
-
-if that returns true and you use KVM_CREATE_IRQCHIP, or if you emulate the
-feature in userspace, then you can enable the feature for KVM_SET_CPUID2.
-
-
-4.47 KVM_PPC_GET_PVINFO
-
-Capability: KVM_CAP_PPC_GET_PVINFO
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_ppc_pvinfo (out)
-Returns: 0 on success, !0 on error
-
-struct kvm_ppc_pvinfo {
-       __u32 flags;
-       __u32 hcall[4];
-       __u8  pad[108];
-};
-
-This ioctl fetches PV specific information that need to be passed to the guest
-using the device tree or other means from vm context.
-
-The hcall array defines 4 instructions that make up a hypercall.
-
-If any additional field gets added to this structure later on, a bit for that
-additional piece of information will be set in the flags bitmap.
-
-The flags bitmap is defined as:
-
-   /* the host supports the ePAPR idle hcall
-   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
-
-4.52 KVM_SET_GSI_ROUTING
-
-Capability: KVM_CAP_IRQ_ROUTING
-Architectures: x86 s390 arm arm64
-Type: vm ioctl
-Parameters: struct kvm_irq_routing (in)
-Returns: 0 on success, -1 on error
-
-Sets the GSI routing table entries, overwriting any previously set entries.
-
-On arm/arm64, GSI routing has the following limitation:
-- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
-
-struct kvm_irq_routing {
-       __u32 nr;
-       __u32 flags;
-       struct kvm_irq_routing_entry entries[0];
-};
-
-No flags are specified so far, the corresponding field must be set to zero.
-
-struct kvm_irq_routing_entry {
-       __u32 gsi;
-       __u32 type;
-       __u32 flags;
-       __u32 pad;
-       union {
-               struct kvm_irq_routing_irqchip irqchip;
-               struct kvm_irq_routing_msi msi;
-               struct kvm_irq_routing_s390_adapter adapter;
-               struct kvm_irq_routing_hv_sint hv_sint;
-               __u32 pad[8];
-       } u;
-};
-
-/* gsi routing entry types */
-#define KVM_IRQ_ROUTING_IRQCHIP 1
-#define KVM_IRQ_ROUTING_MSI 2
-#define KVM_IRQ_ROUTING_S390_ADAPTER 3
-#define KVM_IRQ_ROUTING_HV_SINT 4
-
-flags:
-- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI routing entry
-  type, specifies that the devid field contains a valid value.  The per-VM
-  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
-  the device ID.  If this capability is not available, userspace should
-  never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
-- zero otherwise
-
-struct kvm_irq_routing_irqchip {
-       __u32 irqchip;
-       __u32 pin;
-};
-
-struct kvm_irq_routing_msi {
-       __u32 address_lo;
-       __u32 address_hi;
-       __u32 data;
-       union {
-               __u32 pad;
-               __u32 devid;
-       };
-};
-
-If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
-for the device that wrote the MSI message.  For PCI, this is usually a
-BFD identifier in the lower 16 bits.
-
-On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
-feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
-address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
-address_hi must be zero.
-
-struct kvm_irq_routing_s390_adapter {
-       __u64 ind_addr;
-       __u64 summary_addr;
-       __u64 ind_offset;
-       __u32 summary_offset;
-       __u32 adapter_id;
-};
-
-struct kvm_irq_routing_hv_sint {
-       __u32 vcpu;
-       __u32 sint;
-};
-
-
-4.55 KVM_SET_TSC_KHZ
-
-Capability: KVM_CAP_TSC_CONTROL
-Architectures: x86
-Type: vcpu ioctl
-Parameters: virtual tsc_khz
-Returns: 0 on success, -1 on error
-
-Specifies the tsc frequency for the virtual machine. The unit of the
-frequency is KHz.
-
-
-4.56 KVM_GET_TSC_KHZ
-
-Capability: KVM_CAP_GET_TSC_KHZ
-Architectures: x86
-Type: vcpu ioctl
-Parameters: none
-Returns: virtual tsc-khz on success, negative value on error
-
-Returns the tsc frequency of the guest. The unit of the return value is
-KHz. If the host has unstable tsc this ioctl returns -EIO instead as an
-error.
-
-
-4.57 KVM_GET_LAPIC
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_lapic_state (out)
-Returns: 0 on success, -1 on error
-
-#define KVM_APIC_REG_SIZE 0x400
-struct kvm_lapic_state {
-       char regs[KVM_APIC_REG_SIZE];
-};
-
-Reads the Local APIC registers and copies them into the input argument.  The
-data format and layout are the same as documented in the architecture manual.
-
-If KVM_X2APIC_API_USE_32BIT_IDS feature of KVM_CAP_X2APIC_API is
-enabled, then the format of APIC_ID register depends on the APIC mode
-(reported by MSR_IA32_APICBASE) of its VCPU.  x2APIC stores APIC ID in
-the APIC_ID register (bytes 32-35).  xAPIC only allows an 8-bit APIC ID
-which is stored in bits 31-24 of the APIC register, or equivalently in
-byte 35 of struct kvm_lapic_state's regs field.  KVM_GET_LAPIC must then
-be called after MSR_IA32_APICBASE has been set with KVM_SET_MSR.
-
-If KVM_X2APIC_API_USE_32BIT_IDS feature is disabled, struct kvm_lapic_state
-always uses xAPIC format.
-
-
-4.58 KVM_SET_LAPIC
-
-Capability: KVM_CAP_IRQCHIP
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_lapic_state (in)
-Returns: 0 on success, -1 on error
-
-#define KVM_APIC_REG_SIZE 0x400
-struct kvm_lapic_state {
-       char regs[KVM_APIC_REG_SIZE];
-};
-
-Copies the input argument into the Local APIC registers.  The data format
-and layout are the same as documented in the architecture manual.
-
-The format of the APIC ID register (bytes 32-35 of struct kvm_lapic_state's
-regs field) depends on the state of the KVM_CAP_X2APIC_API capability.
-See the note in KVM_GET_LAPIC.
-
-
-4.59 KVM_IOEVENTFD
-
-Capability: KVM_CAP_IOEVENTFD
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_ioeventfd (in)
-Returns: 0 on success, !0 on error
-
-This ioctl attaches or detaches an ioeventfd to a legal pio/mmio address
-within the guest.  A guest write in the registered address will signal the
-provided event instead of triggering an exit.
-
-struct kvm_ioeventfd {
-       __u64 datamatch;
-       __u64 addr;        /* legal pio/mmio address */
-       __u32 len;         /* 0, 1, 2, 4, or 8 bytes    */
-       __s32 fd;
-       __u32 flags;
-       __u8  pad[36];
-};
-
-For the special case of virtio-ccw devices on s390, the ioevent is matched
-to a subchannel/virtqueue tuple instead.
-
-The following flags are defined:
-
-#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
-#define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
-#define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
-#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
-       (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
-
-If datamatch flag is set, the event will be signaled only if the written value
-to the registered address is equal to datamatch in struct kvm_ioeventfd.
-
-For virtio-ccw devices, addr contains the subchannel id and datamatch the
-virtqueue index.
-
-With KVM_CAP_IOEVENTFD_ANY_LENGTH, a zero length ioeventfd is allowed, and
-the kernel will ignore the length of guest write and may get a faster vmexit.
-The speedup may only apply to specific architectures, but the ioeventfd will
-work anyway.
-
-4.60 KVM_DIRTY_TLB
-
-Capability: KVM_CAP_SW_TLB
-Architectures: ppc
-Type: vcpu ioctl
-Parameters: struct kvm_dirty_tlb (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_dirty_tlb {
-       __u64 bitmap;
-       __u32 num_dirty;
-};
-
-This must be called whenever userspace has changed an entry in the shared
-TLB, prior to calling KVM_RUN on the associated vcpu.
-
-The "bitmap" field is the userspace address of an array.  This array
-consists of a number of bits, equal to the total number of TLB entries as
-determined by the last successful call to KVM_CONFIG_TLB, rounded up to the
-nearest multiple of 64.
-
-Each bit corresponds to one TLB entry, ordered the same as in the shared TLB
-array.
-
-The array is little-endian: the bit 0 is the least significant bit of the
-first byte, bit 8 is the least significant bit of the second byte, etc.
-This avoids any complications with differing word sizes.
-
-The "num_dirty" field is a performance hint for KVM to determine whether it
-should skip processing the bitmap and just invalidate everything.  It must
-be set to the number of set bits in the bitmap.
-
-
-4.62 KVM_CREATE_SPAPR_TCE
-
-Capability: KVM_CAP_SPAPR_TCE
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_create_spapr_tce (in)
-Returns: file descriptor for manipulating the created TCE table
-
-This creates a virtual TCE (translation control entry) table, which
-is an IOMMU for PAPR-style virtual I/O.  It is used to translate
-logical addresses used in virtual I/O into guest physical addresses,
-and provides a scatter/gather capability for PAPR virtual I/O.
-
-/* for KVM_CAP_SPAPR_TCE */
-struct kvm_create_spapr_tce {
-       __u64 liobn;
-       __u32 window_size;
-};
-
-The liobn field gives the logical IO bus number for which to create a
-TCE table.  The window_size field specifies the size of the DMA window
-which this TCE table will translate - the table will contain one 64
-bit TCE entry for every 4kiB of the DMA window.
-
-When the guest issues an H_PUT_TCE hcall on a liobn for which a TCE
-table has been created using this ioctl(), the kernel will handle it
-in real mode, updating the TCE table.  H_PUT_TCE calls for other
-liobns will cause a vm exit and must be handled by userspace.
-
-The return value is a file descriptor which can be passed to mmap(2)
-to map the created TCE table into userspace.  This lets userspace read
-the entries written by kernel-handled H_PUT_TCE calls, and also lets
-userspace update the TCE table directly which is useful in some
-circumstances.
-
-
-4.63 KVM_ALLOCATE_RMA
-
-Capability: KVM_CAP_PPC_RMA
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_allocate_rma (out)
-Returns: file descriptor for mapping the allocated RMA
-
-This allocates a Real Mode Area (RMA) from the pool allocated at boot
-time by the kernel.  An RMA is a physically-contiguous, aligned region
-of memory used on older POWER processors to provide the memory which
-will be accessed by real-mode (MMU off) accesses in a KVM guest.
-POWER processors support a set of sizes for the RMA that usually
-includes 64MB, 128MB, 256MB and some larger powers of two.
-
-/* for KVM_ALLOCATE_RMA */
-struct kvm_allocate_rma {
-       __u64 rma_size;
-};
-
-The return value is a file descriptor which can be passed to mmap(2)
-to map the allocated RMA into userspace.  The mapped area can then be
-passed to the KVM_SET_USER_MEMORY_REGION ioctl to establish it as the
-RMA for a virtual machine.  The size of the RMA in bytes (which is
-fixed at host kernel boot time) is returned in the rma_size field of
-the argument structure.
-
-The KVM_CAP_PPC_RMA capability is 1 or 2 if the KVM_ALLOCATE_RMA ioctl
-is supported; 2 if the processor requires all virtual machines to have
-an RMA, or 1 if the processor can use an RMA but doesn't require it,
-because it supports the Virtual RMA (VRMA) facility.
-
-
-4.64 KVM_NMI
-
-Capability: KVM_CAP_USER_NMI
-Architectures: x86
-Type: vcpu ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-
-Queues an NMI on the thread's vcpu.  Note this is well defined only
-when KVM_CREATE_IRQCHIP has not been called, since this is an interface
-between the virtual cpu core and virtual local APIC.  After KVM_CREATE_IRQCHIP
-has been called, this interface is completely emulated within the kernel.
-
-To use this to emulate the LINT1 input with KVM_CREATE_IRQCHIP, use the
-following algorithm:
-
-  - pause the vcpu
-  - read the local APIC's state (KVM_GET_LAPIC)
-  - check whether changing LINT1 will queue an NMI (see the LVT entry for LINT1)
-  - if so, issue KVM_NMI
-  - resume the vcpu
-
-Some guests configure the LINT1 NMI input to cause a panic, aiding in
-debugging.
-
-
-4.65 KVM_S390_UCAS_MAP
-
-Capability: KVM_CAP_S390_UCONTROL
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_ucas_mapping (in)
-Returns: 0 in case of success
-
-The parameter is defined like this:
-       struct kvm_s390_ucas_mapping {
-               __u64 user_addr;
-               __u64 vcpu_addr;
-               __u64 length;
-       };
-
-This ioctl maps the memory at "user_addr" with the length "length" to
-the vcpu's address space starting at "vcpu_addr". All parameters need to
-be aligned by 1 megabyte.
-
-
-4.66 KVM_S390_UCAS_UNMAP
-
-Capability: KVM_CAP_S390_UCONTROL
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_ucas_mapping (in)
-Returns: 0 in case of success
-
-The parameter is defined like this:
-       struct kvm_s390_ucas_mapping {
-               __u64 user_addr;
-               __u64 vcpu_addr;
-               __u64 length;
-       };
-
-This ioctl unmaps the memory in the vcpu's address space starting at
-"vcpu_addr" with the length "length". The field "user_addr" is ignored.
-All parameters need to be aligned by 1 megabyte.
-
-
-4.67 KVM_S390_VCPU_FAULT
-
-Capability: KVM_CAP_S390_UCONTROL
-Architectures: s390
-Type: vcpu ioctl
-Parameters: vcpu absolute address (in)
-Returns: 0 in case of success
-
-This call creates a page table entry on the virtual cpu's address space
-(for user controlled virtual machines) or the virtual machine's address
-space (for regular virtual machines). This only works for minor faults,
-thus it's recommended to access subject memory page via the user page
-table upfront. This is useful to handle validity intercepts for user
-controlled virtual machines to fault in the virtual cpu's lowcore pages
-prior to calling the KVM_RUN ioctl.
-
-
-4.68 KVM_SET_ONE_REG
-
-Capability: KVM_CAP_ONE_REG
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_one_reg (in)
-Returns: 0 on success, negative value on failure
-Errors:
-  ENOENT:   no such register
-  EINVAL:   invalid register ID, or no such register
-  EPERM:    (arm64) register access not allowed before vcpu finalization
-(These error codes are indicative only: do not rely on a specific error
-code being returned in a specific situation.)
-
-struct kvm_one_reg {
-       __u64 id;
-       __u64 addr;
-};
-
-Using this ioctl, a single vcpu register can be set to a specific value
-defined by user space with the passed in struct kvm_one_reg, where id
-refers to the register identifier as described below and addr is a pointer
-to a variable with the respective size. There can be architecture agnostic
-and architecture specific registers. Each have their own range of operation
-and their own constants and width. To keep track of the implemented
-registers, find a list below:
-
-  Arch  |           Register            | Width (bits)
-        |                               |
-  PPC   | KVM_REG_PPC_HIOR              | 64
-  PPC   | KVM_REG_PPC_IAC1              | 64
-  PPC   | KVM_REG_PPC_IAC2              | 64
-  PPC   | KVM_REG_PPC_IAC3              | 64
-  PPC   | KVM_REG_PPC_IAC4              | 64
-  PPC   | KVM_REG_PPC_DAC1              | 64
-  PPC   | KVM_REG_PPC_DAC2              | 64
-  PPC   | KVM_REG_PPC_DABR              | 64
-  PPC   | KVM_REG_PPC_DSCR              | 64
-  PPC   | KVM_REG_PPC_PURR              | 64
-  PPC   | KVM_REG_PPC_SPURR             | 64
-  PPC   | KVM_REG_PPC_DAR               | 64
-  PPC   | KVM_REG_PPC_DSISR             | 32
-  PPC   | KVM_REG_PPC_AMR               | 64
-  PPC   | KVM_REG_PPC_UAMOR             | 64
-  PPC   | KVM_REG_PPC_MMCR0             | 64
-  PPC   | KVM_REG_PPC_MMCR1             | 64
-  PPC   | KVM_REG_PPC_MMCRA             | 64
-  PPC   | KVM_REG_PPC_MMCR2             | 64
-  PPC   | KVM_REG_PPC_MMCRS             | 64
-  PPC   | KVM_REG_PPC_SIAR              | 64
-  PPC   | KVM_REG_PPC_SDAR              | 64
-  PPC   | KVM_REG_PPC_SIER              | 64
-  PPC   | KVM_REG_PPC_PMC1              | 32
-  PPC   | KVM_REG_PPC_PMC2              | 32
-  PPC   | KVM_REG_PPC_PMC3              | 32
-  PPC   | KVM_REG_PPC_PMC4              | 32
-  PPC   | KVM_REG_PPC_PMC5              | 32
-  PPC   | KVM_REG_PPC_PMC6              | 32
-  PPC   | KVM_REG_PPC_PMC7              | 32
-  PPC   | KVM_REG_PPC_PMC8              | 32
-  PPC   | KVM_REG_PPC_FPR0              | 64
-          ...
-  PPC   | KVM_REG_PPC_FPR31             | 64
-  PPC   | KVM_REG_PPC_VR0               | 128
-          ...
-  PPC   | KVM_REG_PPC_VR31              | 128
-  PPC   | KVM_REG_PPC_VSR0              | 128
-          ...
-  PPC   | KVM_REG_PPC_VSR31             | 128
-  PPC   | KVM_REG_PPC_FPSCR             | 64
-  PPC   | KVM_REG_PPC_VSCR              | 32
-  PPC   | KVM_REG_PPC_VPA_ADDR          | 64
-  PPC   | KVM_REG_PPC_VPA_SLB           | 128
-  PPC   | KVM_REG_PPC_VPA_DTL           | 128
-  PPC   | KVM_REG_PPC_EPCR              | 32
-  PPC   | KVM_REG_PPC_EPR               | 32
-  PPC   | KVM_REG_PPC_TCR               | 32
-  PPC   | KVM_REG_PPC_TSR               | 32
-  PPC   | KVM_REG_PPC_OR_TSR            | 32
-  PPC   | KVM_REG_PPC_CLEAR_TSR         | 32
-  PPC   | KVM_REG_PPC_MAS0              | 32
-  PPC   | KVM_REG_PPC_MAS1              | 32
-  PPC   | KVM_REG_PPC_MAS2              | 64
-  PPC   | KVM_REG_PPC_MAS7_3            | 64
-  PPC   | KVM_REG_PPC_MAS4              | 32
-  PPC   | KVM_REG_PPC_MAS6              | 32
-  PPC   | KVM_REG_PPC_MMUCFG            | 32
-  PPC   | KVM_REG_PPC_TLB0CFG           | 32
-  PPC   | KVM_REG_PPC_TLB1CFG           | 32
-  PPC   | KVM_REG_PPC_TLB2CFG           | 32
-  PPC   | KVM_REG_PPC_TLB3CFG           | 32
-  PPC   | KVM_REG_PPC_TLB0PS            | 32
-  PPC   | KVM_REG_PPC_TLB1PS            | 32
-  PPC   | KVM_REG_PPC_TLB2PS            | 32
-  PPC   | KVM_REG_PPC_TLB3PS            | 32
-  PPC   | KVM_REG_PPC_EPTCFG            | 32
-  PPC   | KVM_REG_PPC_ICP_STATE         | 64
-  PPC   | KVM_REG_PPC_VP_STATE          | 128
-  PPC   | KVM_REG_PPC_TB_OFFSET         | 64
-  PPC   | KVM_REG_PPC_SPMC1             | 32
-  PPC   | KVM_REG_PPC_SPMC2             | 32
-  PPC   | KVM_REG_PPC_IAMR              | 64
-  PPC   | KVM_REG_PPC_TFHAR             | 64
-  PPC   | KVM_REG_PPC_TFIAR             | 64
-  PPC   | KVM_REG_PPC_TEXASR            | 64
-  PPC   | KVM_REG_PPC_FSCR              | 64
-  PPC   | KVM_REG_PPC_PSPB              | 32
-  PPC   | KVM_REG_PPC_EBBHR             | 64
-  PPC   | KVM_REG_PPC_EBBRR             | 64
-  PPC   | KVM_REG_PPC_BESCR             | 64
-  PPC   | KVM_REG_PPC_TAR               | 64
-  PPC   | KVM_REG_PPC_DPDES             | 64
-  PPC   | KVM_REG_PPC_DAWR              | 64
-  PPC   | KVM_REG_PPC_DAWRX             | 64
-  PPC   | KVM_REG_PPC_CIABR             | 64
-  PPC   | KVM_REG_PPC_IC                | 64
-  PPC   | KVM_REG_PPC_VTB               | 64
-  PPC   | KVM_REG_PPC_CSIGR             | 64
-  PPC   | KVM_REG_PPC_TACR              | 64
-  PPC   | KVM_REG_PPC_TCSCR             | 64
-  PPC   | KVM_REG_PPC_PID               | 64
-  PPC   | KVM_REG_PPC_ACOP              | 64
-  PPC   | KVM_REG_PPC_VRSAVE            | 32
-  PPC   | KVM_REG_PPC_LPCR              | 32
-  PPC   | KVM_REG_PPC_LPCR_64           | 64
-  PPC   | KVM_REG_PPC_PPR               | 64
-  PPC   | KVM_REG_PPC_ARCH_COMPAT       | 32
-  PPC   | KVM_REG_PPC_DABRX             | 32
-  PPC   | KVM_REG_PPC_WORT              | 64
-  PPC  | KVM_REG_PPC_SPRG9             | 64
-  PPC  | KVM_REG_PPC_DBSR              | 32
-  PPC   | KVM_REG_PPC_TIDR              | 64
-  PPC   | KVM_REG_PPC_PSSCR             | 64
-  PPC   | KVM_REG_PPC_DEC_EXPIRY        | 64
-  PPC   | KVM_REG_PPC_PTCR              | 64
-  PPC   | KVM_REG_PPC_TM_GPR0           | 64
-          ...
-  PPC   | KVM_REG_PPC_TM_GPR31          | 64
-  PPC   | KVM_REG_PPC_TM_VSR0           | 128
-          ...
-  PPC   | KVM_REG_PPC_TM_VSR63          | 128
-  PPC   | KVM_REG_PPC_TM_CR             | 64
-  PPC   | KVM_REG_PPC_TM_LR             | 64
-  PPC   | KVM_REG_PPC_TM_CTR            | 64
-  PPC   | KVM_REG_PPC_TM_FPSCR          | 64
-  PPC   | KVM_REG_PPC_TM_AMR            | 64
-  PPC   | KVM_REG_PPC_TM_PPR            | 64
-  PPC   | KVM_REG_PPC_TM_VRSAVE         | 64
-  PPC   | KVM_REG_PPC_TM_VSCR           | 32
-  PPC   | KVM_REG_PPC_TM_DSCR           | 64
-  PPC   | KVM_REG_PPC_TM_TAR            | 64
-  PPC   | KVM_REG_PPC_TM_XER            | 64
-        |                               |
-  MIPS  | KVM_REG_MIPS_R0               | 64
-          ...
-  MIPS  | KVM_REG_MIPS_R31              | 64
-  MIPS  | KVM_REG_MIPS_HI               | 64
-  MIPS  | KVM_REG_MIPS_LO               | 64
-  MIPS  | KVM_REG_MIPS_PC               | 64
-  MIPS  | KVM_REG_MIPS_CP0_INDEX        | 32
-  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO0     | 64
-  MIPS  | KVM_REG_MIPS_CP0_ENTRYLO1     | 64
-  MIPS  | KVM_REG_MIPS_CP0_CONTEXT      | 64
-  MIPS  | KVM_REG_MIPS_CP0_CONTEXTCONFIG| 32
-  MIPS  | KVM_REG_MIPS_CP0_USERLOCAL    | 64
-  MIPS  | KVM_REG_MIPS_CP0_XCONTEXTCONFIG| 64
-  MIPS  | KVM_REG_MIPS_CP0_PAGEMASK     | 32
-  MIPS  | KVM_REG_MIPS_CP0_PAGEGRAIN    | 32
-  MIPS  | KVM_REG_MIPS_CP0_SEGCTL0      | 64
-  MIPS  | KVM_REG_MIPS_CP0_SEGCTL1      | 64
-  MIPS  | KVM_REG_MIPS_CP0_SEGCTL2      | 64
-  MIPS  | KVM_REG_MIPS_CP0_PWBASE       | 64
-  MIPS  | KVM_REG_MIPS_CP0_PWFIELD      | 64
-  MIPS  | KVM_REG_MIPS_CP0_PWSIZE       | 64
-  MIPS  | KVM_REG_MIPS_CP0_WIRED        | 32
-  MIPS  | KVM_REG_MIPS_CP0_PWCTL        | 32
-  MIPS  | KVM_REG_MIPS_CP0_HWRENA       | 32
-  MIPS  | KVM_REG_MIPS_CP0_BADVADDR     | 64
-  MIPS  | KVM_REG_MIPS_CP0_BADINSTR     | 32
-  MIPS  | KVM_REG_MIPS_CP0_BADINSTRP    | 32
-  MIPS  | KVM_REG_MIPS_CP0_COUNT        | 32
-  MIPS  | KVM_REG_MIPS_CP0_ENTRYHI      | 64
-  MIPS  | KVM_REG_MIPS_CP0_COMPARE      | 32
-  MIPS  | KVM_REG_MIPS_CP0_STATUS       | 32
-  MIPS  | KVM_REG_MIPS_CP0_INTCTL       | 32
-  MIPS  | KVM_REG_MIPS_CP0_CAUSE        | 32
-  MIPS  | KVM_REG_MIPS_CP0_EPC          | 64
-  MIPS  | KVM_REG_MIPS_CP0_PRID         | 32
-  MIPS  | KVM_REG_MIPS_CP0_EBASE        | 64
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG       | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG1      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG2      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG3      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG4      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG5      | 32
-  MIPS  | KVM_REG_MIPS_CP0_CONFIG7      | 32
-  MIPS  | KVM_REG_MIPS_CP0_XCONTEXT     | 64
-  MIPS  | KVM_REG_MIPS_CP0_ERROREPC     | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH1    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH2    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH3    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH4    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH5    | 64
-  MIPS  | KVM_REG_MIPS_CP0_KSCRATCH6    | 64
-  MIPS  | KVM_REG_MIPS_CP0_MAAR(0..63)  | 64
-  MIPS  | KVM_REG_MIPS_COUNT_CTL        | 64
-  MIPS  | KVM_REG_MIPS_COUNT_RESUME     | 64
-  MIPS  | KVM_REG_MIPS_COUNT_HZ         | 64
-  MIPS  | KVM_REG_MIPS_FPR_32(0..31)    | 32
-  MIPS  | KVM_REG_MIPS_FPR_64(0..31)    | 64
-  MIPS  | KVM_REG_MIPS_VEC_128(0..31)   | 128
-  MIPS  | KVM_REG_MIPS_FCR_IR           | 32
-  MIPS  | KVM_REG_MIPS_FCR_CSR          | 32
-  MIPS  | KVM_REG_MIPS_MSA_IR           | 32
-  MIPS  | KVM_REG_MIPS_MSA_CSR          | 32
-
-ARM registers are mapped using the lower 32 bits.  The upper 16 of that
-is the register group type, or coprocessor number:
-
-ARM core registers have the following id bit patterns:
-  0x4020 0000 0010 <index into the kvm_regs struct:16>
-
-ARM 32-bit CP15 registers have the following id bit patterns:
-  0x4020 0000 000F <zero:1> <crn:4> <crm:4> <opc1:4> <opc2:3>
-
-ARM 64-bit CP15 registers have the following id bit patterns:
-  0x4030 0000 000F <zero:1> <zero:4> <crm:4> <opc1:4> <zero:3>
-
-ARM CCSIDR registers are demultiplexed by CSSELR value:
-  0x4020 0000 0011 00 <csselr:8>
-
-ARM 32-bit VFP control registers have the following id bit patterns:
-  0x4020 0000 0012 1 <regno:12>
-
-ARM 64-bit FP registers have the following id bit patterns:
-  0x4030 0000 0012 0 <regno:12>
-
-ARM firmware pseudo-registers have the following bit pattern:
-  0x4030 0000 0014 <regno:16>
-
-
-arm64 registers are mapped using the lower 32 bits. The upper 16 of
-that is the register group type, or coprocessor number:
-
-arm64 core/FP-SIMD registers have the following id bit patterns. Note
-that the size of the access is variable, as the kvm_regs structure
-contains elements ranging from 32 to 128 bits. The index is a 32bit
-value in the kvm_regs structure seen as a 32bit array.
-  0x60x0 0000 0010 <index into the kvm_regs struct:16>
-
-Specifically:
-    Encoding            Register  Bits  kvm_regs member
-----------------------------------------------------------------
-  0x6030 0000 0010 0000 X0          64  regs.regs[0]
-  0x6030 0000 0010 0002 X1          64  regs.regs[1]
-    ...
-  0x6030 0000 0010 003c X30         64  regs.regs[30]
-  0x6030 0000 0010 003e SP          64  regs.sp
-  0x6030 0000 0010 0040 PC          64  regs.pc
-  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
-  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
-  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
-  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
-  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
-  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
-  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
-  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
-  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]    (*)
-  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]    (*)
-    ...
-  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]   (*)
-  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
-  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
-
-(*) These encodings are not accepted for SVE-enabled vcpus.  See
-    KVM_ARM_VCPU_INIT.
-
-    The equivalent register content can be accessed via bits [127:0] of
-    the corresponding SVE Zn registers instead for vcpus that have SVE
-    enabled (see below).
-
-arm64 CCSIDR registers are demultiplexed by CSSELR value:
-  0x6020 0000 0011 00 <csselr:8>
-
-arm64 system registers have the following id bit patterns:
-  0x6030 0000 0013 <op0:2> <op1:3> <crn:4> <crm:4> <op2:3>
-
-arm64 firmware pseudo-registers have the following bit pattern:
-  0x6030 0000 0014 <regno:16>
-
-arm64 SVE registers have the following bit patterns:
-  0x6080 0000 0015 00 <n:5> <slice:5>   Zn bits[2048*slice + 2047 : 2048*slice]
-  0x6050 0000 0015 04 <n:4> <slice:5>   Pn bits[256*slice + 255 : 256*slice]
-  0x6050 0000 0015 060 <slice:5>        FFR bits[256*slice + 255 : 256*slice]
-  0x6060 0000 0015 ffff                 KVM_REG_ARM64_SVE_VLS pseudo-register
-
-Access to register IDs where 2048 * slice >= 128 * max_vq will fail with
-ENOENT.  max_vq is the vcpu's maximum supported vector length in 128-bit
-quadwords: see (**) below.
-
-These registers are only accessible on vcpus for which SVE is enabled.
-See KVM_ARM_VCPU_INIT for details.
-
-In addition, except for KVM_REG_ARM64_SVE_VLS, these registers are not
-accessible until the vcpu's SVE configuration has been finalized
-using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).  See KVM_ARM_VCPU_INIT
-and KVM_ARM_VCPU_FINALIZE for more information about this procedure.
-
-KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector
-lengths supported by the vcpu to be discovered and configured by
-userspace.  When transferred to or from user memory via KVM_GET_ONE_REG
-or KVM_SET_ONE_REG, the value of this register is of type
-__u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths as
-follows:
-
-__u64 vector_lengths[KVM_ARM64_SVE_VLS_WORDS];
-
-if (vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX &&
-    ((vector_lengths[(vq - KVM_ARM64_SVE_VQ_MIN) / 64] >>
-               ((vq - KVM_ARM64_SVE_VQ_MIN) % 64)) & 1))
-       /* Vector length vq * 16 bytes supported */
-else
-       /* Vector length vq * 16 bytes not supported */
-
-(**) The maximum value vq for which the above condition is true is
-max_vq.  This is the maximum vector length available to the guest on
-this vcpu, and determines which register slices are visible through
-this ioctl interface.
-
-(See Documentation/arm64/sve.rst for an explanation of the "vq"
-nomenclature.)
-
-KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT.
-KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that
-the host supports.
-
-Userspace may subsequently modify it if desired until the vcpu's SVE
-configuration is finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE).
-
-Apart from simply removing all vector lengths from the host set that
-exceed some value, support for arbitrarily chosen sets of vector lengths
-is hardware-dependent and may not be available.  Attempting to configure
-an invalid set of vector lengths via KVM_SET_ONE_REG will fail with
-EINVAL.
-
-After the vcpu's SVE configuration is finalized, further attempts to
-write this register will fail with EPERM.
-
-
-MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
-the register group type:
-
-MIPS core registers (see above) have the following id bit patterns:
-  0x7030 0000 0000 <reg:16>
-
-MIPS CP0 registers (see KVM_REG_MIPS_CP0_* above) have the following id bit
-patterns depending on whether they're 32-bit or 64-bit registers:
-  0x7020 0000 0001 00 <reg:5> <sel:3>   (32-bit)
-  0x7030 0000 0001 00 <reg:5> <sel:3>   (64-bit)
-
-Note: KVM_REG_MIPS_CP0_ENTRYLO0 and KVM_REG_MIPS_CP0_ENTRYLO1 are the MIPS64
-versions of the EntryLo registers regardless of the word size of the host
-hardware, host kernel, guest, and whether XPA is present in the guest, i.e.
-with the RI and XI bits (if they exist) in bits 63 and 62 respectively, and
-the PFNX field starting at bit 30.
-
-MIPS MAARs (see KVM_REG_MIPS_CP0_MAAR(*) above) have the following id bit
-patterns:
-  0x7030 0000 0001 01 <reg:8>
-
-MIPS KVM control registers (see above) have the following id bit patterns:
-  0x7030 0000 0002 <reg:16>
-
-MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following
-id bit patterns depending on the size of the register being accessed. They are
-always accessed according to the current guest FPU mode (Status.FR and
-Config5.FRE), i.e. as the guest would see them, and they become unpredictable
-if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector
-registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they
-overlap the FPU registers:
-  0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
-  0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers)
-  0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers)
-
-MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the
-following id bit patterns:
-  0x7020 0000 0003 01 <0:3> <reg:5>
-
-MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the
-following id bit patterns:
-  0x7020 0000 0003 02 <0:3> <reg:5>
-
-
-4.69 KVM_GET_ONE_REG
-
-Capability: KVM_CAP_ONE_REG
-Architectures: all
-Type: vcpu ioctl
-Parameters: struct kvm_one_reg (in and out)
-Returns: 0 on success, negative value on failure
-Errors include:
-  ENOENT:   no such register
-  EINVAL:   invalid register ID, or no such register
-  EPERM:    (arm64) register access not allowed before vcpu finalization
-(These error codes are indicative only: do not rely on a specific error
-code being returned in a specific situation.)
-
-This ioctl allows to receive the value of a single register implemented
-in a vcpu. The register to read is indicated by the "id" field of the
-kvm_one_reg struct passed in. On success, the register value can be found
-at the memory location pointed to by "addr".
-
-The list of registers accessible using this interface is identical to the
-list in 4.68.
-
-
-4.70 KVM_KVMCLOCK_CTRL
-
-Capability: KVM_CAP_KVMCLOCK_CTRL
-Architectures: Any that implement pvclocks (currently x86 only)
-Type: vcpu ioctl
-Parameters: None
-Returns: 0 on success, -1 on error
-
-This signals to the host kernel that the specified guest is being paused by
-userspace.  The host will set a flag in the pvclock structure that is checked
-from the soft lockup watchdog.  The flag is part of the pvclock structure that
-is shared between guest and host, specifically the second bit of the flags
-field of the pvclock_vcpu_time_info structure.  It will be set exclusively by
-the host and read/cleared exclusively by the guest.  The guest operation of
-checking and clearing the flag must an atomic operation so
-load-link/store-conditional, or equivalent must be used.  There are two cases
-where the guest will clear the flag: when the soft lockup watchdog timer resets
-itself or when a soft lockup is detected.  This ioctl can be called any time
-after pausing the vcpu, but before it is resumed.
-
-
-4.71 KVM_SIGNAL_MSI
-
-Capability: KVM_CAP_SIGNAL_MSI
-Architectures: x86 arm arm64
-Type: vm ioctl
-Parameters: struct kvm_msi (in)
-Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
-
-Directly inject a MSI message. Only valid with in-kernel irqchip that handles
-MSI messages.
-
-struct kvm_msi {
-       __u32 address_lo;
-       __u32 address_hi;
-       __u32 data;
-       __u32 flags;
-       __u32 devid;
-       __u8  pad[12];
-};
-
-flags: KVM_MSI_VALID_DEVID: devid contains a valid value.  The per-VM
-  KVM_CAP_MSI_DEVID capability advertises the requirement to provide
-  the device ID.  If this capability is not available, userspace
-  should never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
-
-If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
-for the device that wrote the MSI message.  For PCI, this is usually a
-BFD identifier in the lower 16 bits.
-
-On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
-feature of KVM_CAP_X2APIC_API capability is enabled.  If it is enabled,
-address_hi bits 31-8 provide bits 31-8 of the destination id.  Bits 7-0 of
-address_hi must be zero.
-
-
-4.71 KVM_CREATE_PIT2
-
-Capability: KVM_CAP_PIT2
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pit_config (in)
-Returns: 0 on success, -1 on error
-
-Creates an in-kernel device model for the i8254 PIT. This call is only valid
-after enabling in-kernel irqchip support via KVM_CREATE_IRQCHIP. The following
-parameters have to be passed:
-
-struct kvm_pit_config {
-       __u32 flags;
-       __u32 pad[15];
-};
-
-Valid flags are:
-
-#define KVM_PIT_SPEAKER_DUMMY     1 /* emulate speaker port stub */
-
-PIT timer interrupts may use a per-VM kernel thread for injection. If it
-exists, this thread will have a name of the following pattern:
-
-kvm-pit/<owner-process-pid>
-
-When running a guest with elevated priorities, the scheduling parameters of
-this thread may have to be adjusted accordingly.
-
-This IOCTL replaces the obsolete KVM_CREATE_PIT.
-
-
-4.72 KVM_GET_PIT2
-
-Capability: KVM_CAP_PIT_STATE2
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pit_state2 (out)
-Returns: 0 on success, -1 on error
-
-Retrieves the state of the in-kernel PIT model. Only valid after
-KVM_CREATE_PIT2. The state is returned in the following structure:
-
-struct kvm_pit_state2 {
-       struct kvm_pit_channel_state channels[3];
-       __u32 flags;
-       __u32 reserved[9];
-};
-
-Valid flags are:
-
-/* disable PIT in HPET legacy mode */
-#define KVM_PIT_FLAGS_HPET_LEGACY  0x00000001
-
-This IOCTL replaces the obsolete KVM_GET_PIT.
-
-
-4.73 KVM_SET_PIT2
-
-Capability: KVM_CAP_PIT_STATE2
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pit_state2 (in)
-Returns: 0 on success, -1 on error
-
-Sets the state of the in-kernel PIT model. Only valid after KVM_CREATE_PIT2.
-See KVM_GET_PIT2 for details on struct kvm_pit_state2.
-
-This IOCTL replaces the obsolete KVM_SET_PIT.
-
-
-4.74 KVM_PPC_GET_SMMU_INFO
-
-Capability: KVM_CAP_PPC_GET_SMMU_INFO
-Architectures: powerpc
-Type: vm ioctl
-Parameters: None
-Returns: 0 on success, -1 on error
-
-This populates and returns a structure describing the features of
-the "Server" class MMU emulation supported by KVM.
-This can in turn be used by userspace to generate the appropriate
-device-tree properties for the guest operating system.
-
-The structure contains some global information, followed by an
-array of supported segment page sizes:
-
-      struct kvm_ppc_smmu_info {
-            __u64 flags;
-            __u32 slb_size;
-            __u32 pad;
-            struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
-      };
-
-The supported flags are:
-
-    - KVM_PPC_PAGE_SIZES_REAL:
-        When that flag is set, guest page sizes must "fit" the backing
-        store page sizes. When not set, any page size in the list can
-        be used regardless of how they are backed by userspace.
-
-    - KVM_PPC_1T_SEGMENTS
-        The emulated MMU supports 1T segments in addition to the
-        standard 256M ones.
-
-    - KVM_PPC_NO_HASH
-       This flag indicates that HPT guests are not supported by KVM,
-       thus all guests must use radix MMU mode.
-
-The "slb_size" field indicates how many SLB entries are supported
-
-The "sps" array contains 8 entries indicating the supported base
-page sizes for a segment in increasing order. Each entry is defined
-as follow:
-
-   struct kvm_ppc_one_seg_page_size {
-       __u32 page_shift;       /* Base page shift of segment (or 0) */
-       __u32 slb_enc;          /* SLB encoding for BookS */
-       struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ];
-   };
-
-An entry with a "page_shift" of 0 is unused. Because the array is
-organized in increasing order, a lookup can stop when encoutering
-such an entry.
-
-The "slb_enc" field provides the encoding to use in the SLB for the
-page size. The bits are in positions such as the value can directly
-be OR'ed into the "vsid" argument of the slbmte instruction.
-
-The "enc" array is a list which for each of those segment base page
-size provides the list of supported actual page sizes (which can be
-only larger or equal to the base page size), along with the
-corresponding encoding in the hash PTE. Similarly, the array is
-8 entries sorted by increasing sizes and an entry with a "0" shift
-is an empty entry and a terminator:
-
-   struct kvm_ppc_one_page_size {
-       __u32 page_shift;       /* Page shift (or 0) */
-       __u32 pte_enc;          /* Encoding in the HPTE (>>12) */
-   };
-
-The "pte_enc" field provides a value that can OR'ed into the hash
-PTE's RPN field (ie, it needs to be shifted left by 12 to OR it
-into the hash PTE second double word).
-
-4.75 KVM_IRQFD
-
-Capability: KVM_CAP_IRQFD
-Architectures: x86 s390 arm arm64
-Type: vm ioctl
-Parameters: struct kvm_irqfd (in)
-Returns: 0 on success, -1 on error
-
-Allows setting an eventfd to directly trigger a guest interrupt.
-kvm_irqfd.fd specifies the file descriptor to use as the eventfd and
-kvm_irqfd.gsi specifies the irqchip pin toggled by this event.  When
-an event is triggered on the eventfd, an interrupt is injected into
-the guest using the specified gsi pin.  The irqfd is removed using
-the KVM_IRQFD_FLAG_DEASSIGN flag, specifying both kvm_irqfd.fd
-and kvm_irqfd.gsi.
-
-With KVM_CAP_IRQFD_RESAMPLE, KVM_IRQFD supports a de-assert and notify
-mechanism allowing emulation of level-triggered, irqfd-based
-interrupts.  When KVM_IRQFD_FLAG_RESAMPLE is set the user must pass an
-additional eventfd in the kvm_irqfd.resamplefd field.  When operating
-in resample mode, posting of an interrupt through kvm_irq.fd asserts
-the specified gsi in the irqchip.  When the irqchip is resampled, such
-as from an EOI, the gsi is de-asserted and the user is notified via
-kvm_irqfd.resamplefd.  It is the user's responsibility to re-queue
-the interrupt if the device making use of it still requires service.
-Note that closing the resamplefd is not sufficient to disable the
-irqfd.  The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
-and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
-
-On arm/arm64, gsi routing being supported, the following can happen:
-- in case no routing entry is associated to this gsi, injection fails
-- in case the gsi is associated to an irqchip routing entry,
-  irqchip.pin + 32 corresponds to the injected SPI ID.
-- in case the gsi is associated to an MSI routing entry, the MSI
-  message and device ID are translated into an LPI (support restricted
-  to GICv3 ITS in-kernel emulation).
-
-4.76 KVM_PPC_ALLOCATE_HTAB
-
-Capability: KVM_CAP_PPC_ALLOC_HTAB
-Architectures: powerpc
-Type: vm ioctl
-Parameters: Pointer to u32 containing hash table order (in/out)
-Returns: 0 on success, -1 on error
-
-This requests the host kernel to allocate an MMU hash table for a
-guest using the PAPR paravirtualization interface.  This only does
-anything if the kernel is configured to use the Book 3S HV style of
-virtualization.  Otherwise the capability doesn't exist and the ioctl
-returns an ENOTTY error.  The rest of this description assumes Book 3S
-HV.
-
-There must be no vcpus running when this ioctl is called; if there
-are, it will do nothing and return an EBUSY error.
-
-The parameter is a pointer to a 32-bit unsigned integer variable
-containing the order (log base 2) of the desired size of the hash
-table, which must be between 18 and 46.  On successful return from the
-ioctl, the value will not be changed by the kernel.
-
-If no hash table has been allocated when any vcpu is asked to run
-(with the KVM_RUN ioctl), the host kernel will allocate a
-default-sized hash table (16 MB).
-
-If this ioctl is called when a hash table has already been allocated,
-with a different order from the existing hash table, the existing hash
-table will be freed and a new one allocated.  If this is ioctl is
-called when a hash table has already been allocated of the same order
-as specified, the kernel will clear out the existing hash table (zero
-all HPTEs).  In either case, if the guest is using the virtualized
-real-mode area (VRMA) facility, the kernel will re-create the VMRA
-HPTEs on the next KVM_RUN of any vcpu.
-
-4.77 KVM_S390_INTERRUPT
-
-Capability: basic
-Architectures: s390
-Type: vm ioctl, vcpu ioctl
-Parameters: struct kvm_s390_interrupt (in)
-Returns: 0 on success, -1 on error
-
-Allows to inject an interrupt to the guest. Interrupts can be floating
-(vm ioctl) or per cpu (vcpu ioctl), depending on the interrupt type.
-
-Interrupt parameters are passed via kvm_s390_interrupt:
-
-struct kvm_s390_interrupt {
-       __u32 type;
-       __u32 parm;
-       __u64 parm64;
-};
-
-type can be one of the following:
-
-KVM_S390_SIGP_STOP (vcpu) - sigp stop; optional flags in parm
-KVM_S390_PROGRAM_INT (vcpu) - program check; code in parm
-KVM_S390_SIGP_SET_PREFIX (vcpu) - sigp set prefix; prefix address in parm
-KVM_S390_RESTART (vcpu) - restart
-KVM_S390_INT_CLOCK_COMP (vcpu) - clock comparator interrupt
-KVM_S390_INT_CPU_TIMER (vcpu) - CPU timer interrupt
-KVM_S390_INT_VIRTIO (vm) - virtio external interrupt; external interrupt
-                          parameters in parm and parm64
-KVM_S390_INT_SERVICE (vm) - sclp external interrupt; sclp parameter in parm
-KVM_S390_INT_EMERGENCY (vcpu) - sigp emergency; source cpu in parm
-KVM_S390_INT_EXTERNAL_CALL (vcpu) - sigp external call; source cpu in parm
-KVM_S390_INT_IO(ai,cssid,ssid,schid) (vm) - compound value to indicate an
-    I/O interrupt (ai - adapter interrupt; cssid,ssid,schid - subchannel);
-    I/O interruption parameters in parm (subchannel) and parm64 (intparm,
-    interruption subclass)
-KVM_S390_MCHK (vm, vcpu) - machine check interrupt; cr 14 bits in parm,
-                           machine check interrupt code in parm64 (note that
-                           machine checks needing further payload are not
-                           supported by this ioctl)
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-4.78 KVM_PPC_GET_HTAB_FD
-
-Capability: KVM_CAP_PPC_HTAB_FD
-Architectures: powerpc
-Type: vm ioctl
-Parameters: Pointer to struct kvm_get_htab_fd (in)
-Returns: file descriptor number (>= 0) on success, -1 on error
-
-This returns a file descriptor that can be used either to read out the
-entries in the guest's hashed page table (HPT), or to write entries to
-initialize the HPT.  The returned fd can only be written to if the
-KVM_GET_HTAB_WRITE bit is set in the flags field of the argument, and
-can only be read if that bit is clear.  The argument struct looks like
-this:
-
-/* For KVM_PPC_GET_HTAB_FD */
-struct kvm_get_htab_fd {
-       __u64   flags;
-       __u64   start_index;
-       __u64   reserved[2];
-};
-
-/* Values for kvm_get_htab_fd.flags */
-#define KVM_GET_HTAB_BOLTED_ONLY       ((__u64)0x1)
-#define KVM_GET_HTAB_WRITE             ((__u64)0x2)
-
-The `start_index' field gives the index in the HPT of the entry at
-which to start reading.  It is ignored when writing.
-
-Reads on the fd will initially supply information about all
-"interesting" HPT entries.  Interesting entries are those with the
-bolted bit set, if the KVM_GET_HTAB_BOLTED_ONLY bit is set, otherwise
-all entries.  When the end of the HPT is reached, the read() will
-return.  If read() is called again on the fd, it will start again from
-the beginning of the HPT, but will only return HPT entries that have
-changed since they were last read.
-
-Data read or written is structured as a header (8 bytes) followed by a
-series of valid HPT entries (16 bytes) each.  The header indicates how
-many valid HPT entries there are and how many invalid entries follow
-the valid entries.  The invalid entries are not represented explicitly
-in the stream.  The header format is:
-
-struct kvm_get_htab_header {
-       __u32   index;
-       __u16   n_valid;
-       __u16   n_invalid;
-};
-
-Writes to the fd create HPT entries starting at the index given in the
-header; first `n_valid' valid entries with contents from the data
-written, then `n_invalid' invalid entries, invalidating any previously
-valid entries found.
-
-4.79 KVM_CREATE_DEVICE
-
-Capability: KVM_CAP_DEVICE_CTRL
-Type: vm ioctl
-Parameters: struct kvm_create_device (in/out)
-Returns: 0 on success, -1 on error
-Errors:
-  ENODEV: The device type is unknown or unsupported
-  EEXIST: Device already created, and this type of device may not
-          be instantiated multiple times
-
-  Other error conditions may be defined by individual device types or
-  have their standard meanings.
-
-Creates an emulated device in the kernel.  The file descriptor returned
-in fd can be used with KVM_SET/GET/HAS_DEVICE_ATTR.
-
-If the KVM_CREATE_DEVICE_TEST flag is set, only test whether the
-device type is supported (not necessarily whether it can be created
-in the current vm).
-
-Individual devices should not define flags.  Attributes should be used
-for specifying any behavior that is not implied by the device type
-number.
-
-struct kvm_create_device {
-       __u32   type;   /* in: KVM_DEV_TYPE_xxx */
-       __u32   fd;     /* out: device handle */
-       __u32   flags;  /* in: KVM_CREATE_DEVICE_xxx */
-};
-
-4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR
-
-Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
-  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
-Type: device ioctl, vm ioctl, vcpu ioctl
-Parameters: struct kvm_device_attr
-Returns: 0 on success, -1 on error
-Errors:
-  ENXIO:  The group or attribute is unknown/unsupported for this device
-          or hardware support is missing.
-  EPERM:  The attribute cannot (currently) be accessed this way
-          (e.g. read-only attribute, or attribute that only makes
-          sense when the device is in a different state)
-
-  Other error conditions may be defined by individual device types.
-
-Gets/sets a specified piece of device configuration and/or state.  The
-semantics are device-specific.  See individual device documentation in
-the "devices" directory.  As with ONE_REG, the size of the data
-transferred is defined by the particular attribute.
-
-struct kvm_device_attr {
-       __u32   flags;          /* no flags currently defined */
-       __u32   group;          /* device-defined */
-       __u64   attr;           /* group-defined */
-       __u64   addr;           /* userspace address of attr data */
-};
-
-4.81 KVM_HAS_DEVICE_ATTR
-
-Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
-  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
-Type: device ioctl, vm ioctl, vcpu ioctl
-Parameters: struct kvm_device_attr
-Returns: 0 on success, -1 on error
-Errors:
-  ENXIO:  The group or attribute is unknown/unsupported for this device
-          or hardware support is missing.
-
-Tests whether a device supports a particular attribute.  A successful
-return indicates the attribute is implemented.  It does not necessarily
-indicate that the attribute can be read or written in the device's
-current state.  "addr" is ignored.
-
-4.82 KVM_ARM_VCPU_INIT
-
-Capability: basic
-Architectures: arm, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_vcpu_init (in)
-Returns: 0 on success; -1 on error
-Errors:
-  EINVAL:    the target is unknown, or the combination of features is invalid.
-  ENOENT:    a features bit specified is unknown.
-
-This tells KVM what type of CPU to present to the guest, and what
-optional features it should have.  This will cause a reset of the cpu
-registers to their initial values.  If this is not called, KVM_RUN will
-return ENOEXEC for that vcpu.
-
-Note that because some registers reflect machine topology, all vcpus
-should be created before this ioctl is invoked.
-
-Userspace can call this function multiple times for a given vcpu, including
-after the vcpu has been run. This will reset the vcpu to its initial
-state. All calls to this function after the initial call must use the same
-target and same set of feature flags, otherwise EINVAL will be returned.
-
-Possible features:
-       - KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
-         Depends on KVM_CAP_ARM_PSCI.  If not set, the CPU will be powered on
-         and execute guest code when KVM_RUN is called.
-       - KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
-         Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
-       - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 (or a future revision
-          backward compatible with v0.2) for the CPU.
-         Depends on KVM_CAP_ARM_PSCI_0_2.
-       - KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
-         Depends on KVM_CAP_ARM_PMU_V3.
-
-       - KVM_ARM_VCPU_PTRAUTH_ADDRESS: Enables Address Pointer authentication
-         for arm64 only.
-         Depends on KVM_CAP_ARM_PTRAUTH_ADDRESS.
-         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
-         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
-         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
-         requested.
-
-       - KVM_ARM_VCPU_PTRAUTH_GENERIC: Enables Generic Pointer authentication
-         for arm64 only.
-         Depends on KVM_CAP_ARM_PTRAUTH_GENERIC.
-         If KVM_CAP_ARM_PTRAUTH_ADDRESS and KVM_CAP_ARM_PTRAUTH_GENERIC are
-         both present, then both KVM_ARM_VCPU_PTRAUTH_ADDRESS and
-         KVM_ARM_VCPU_PTRAUTH_GENERIC must be requested or neither must be
-         requested.
-
-       - KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only).
-         Depends on KVM_CAP_ARM_SVE.
-         Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
-
-          * After KVM_ARM_VCPU_INIT:
-
-             - KVM_REG_ARM64_SVE_VLS may be read using KVM_GET_ONE_REG: the
-               initial value of this pseudo-register indicates the best set of
-               vector lengths possible for a vcpu on this host.
-
-          * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
-
-             - KVM_RUN and KVM_GET_REG_LIST are not available;
-
-             - KVM_GET_ONE_REG and KVM_SET_ONE_REG cannot be used to access
-               the scalable archietctural SVE registers
-               KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() or
-               KVM_REG_ARM64_SVE_FFR;
-
-             - KVM_REG_ARM64_SVE_VLS may optionally be written using
-               KVM_SET_ONE_REG, to modify the set of vector lengths available
-               for the vcpu.
-
-          * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE):
-
-             - the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can
-               no longer be written using KVM_SET_ONE_REG.
-
-4.83 KVM_ARM_PREFERRED_TARGET
-
-Capability: basic
-Architectures: arm, arm64
-Type: vm ioctl
-Parameters: struct struct kvm_vcpu_init (out)
-Returns: 0 on success; -1 on error
-Errors:
-  ENODEV:    no preferred target available for the host
-
-This queries KVM for preferred CPU target type which can be emulated
-by KVM on underlying host.
-
-The ioctl returns struct kvm_vcpu_init instance containing information
-about preferred CPU target type and recommended features for it.  The
-kvm_vcpu_init->features bitmap returned will have feature bits set if
-the preferred target recommends setting these features, but this is
-not mandatory.
-
-The information returned by this ioctl can be used to prepare an instance
-of struct kvm_vcpu_init for KVM_ARM_VCPU_INIT ioctl which will result in
-in VCPU matching underlying host.
-
-
-4.84 KVM_GET_REG_LIST
-
-Capability: basic
-Architectures: arm, arm64, mips
-Type: vcpu ioctl
-Parameters: struct kvm_reg_list (in/out)
-Returns: 0 on success; -1 on error
-Errors:
-  E2BIG:     the reg index list is too big to fit in the array specified by
-             the user (the number required will be written into n).
-
-struct kvm_reg_list {
-       __u64 n; /* number of registers in reg[] */
-       __u64 reg[0];
-};
-
-This ioctl returns the guest registers that are supported for the
-KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
-
-
-4.85 KVM_ARM_SET_DEVICE_ADDR (deprecated)
-
-Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
-Architectures: arm, arm64
-Type: vm ioctl
-Parameters: struct kvm_arm_device_address (in)
-Returns: 0 on success, -1 on error
-Errors:
-  ENODEV: The device id is unknown
-  ENXIO:  Device not supported on current system
-  EEXIST: Address already set
-  E2BIG:  Address outside guest physical address space
-  EBUSY:  Address overlaps with other device range
-
-struct kvm_arm_device_addr {
-       __u64 id;
-       __u64 addr;
-};
-
-Specify a device address in the guest's physical address space where guests
-can access emulated or directly exposed devices, which the host kernel needs
-to know about. The id field is an architecture specific identifier for a
-specific device.
-
-ARM/arm64 divides the id field into two parts, a device id and an
-address type id specific to the individual device.
-
-  bits:  | 63        ...       32 | 31    ...    16 | 15    ...    0 |
-  field: |        0x00000000      |     device id   |  addr type id  |
-
-ARM/arm64 currently only require this when using the in-kernel GIC
-support for the hardware VGIC features, using KVM_ARM_DEVICE_VGIC_V2
-as the device id.  When setting the base address for the guest's
-mapping of the VGIC virtual CPU and distributor interface, the ioctl
-must be called after calling KVM_CREATE_IRQCHIP, but before calling
-KVM_RUN on any of the VCPUs.  Calling this ioctl twice for any of the
-base addresses will return -EEXIST.
-
-Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
-should be used instead.
-
-
-4.86 KVM_PPC_RTAS_DEFINE_TOKEN
-
-Capability: KVM_CAP_PPC_RTAS
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_rtas_token_args
-Returns: 0 on success, -1 on error
-
-Defines a token value for a RTAS (Run Time Abstraction Services)
-service in order to allow it to be handled in the kernel.  The
-argument struct gives the name of the service, which must be the name
-of a service that has a kernel-side implementation.  If the token
-value is non-zero, it will be associated with that service, and
-subsequent RTAS calls by the guest specifying that token will be
-handled by the kernel.  If the token value is 0, then any token
-associated with the service will be forgotten, and subsequent RTAS
-calls by the guest for that service will be passed to userspace to be
-handled.
-
-4.87 KVM_SET_GUEST_DEBUG
-
-Capability: KVM_CAP_SET_GUEST_DEBUG
-Architectures: x86, s390, ppc, arm64
-Type: vcpu ioctl
-Parameters: struct kvm_guest_debug (in)
-Returns: 0 on success; -1 on error
-
-struct kvm_guest_debug {
-       __u32 control;
-       __u32 pad;
-       struct kvm_guest_debug_arch arch;
-};
-
-Set up the processor specific debug registers and configure vcpu for
-handling guest debug events. There are two parts to the structure, the
-first a control bitfield indicates the type of debug events to handle
-when running. Common control bits are:
-
-  - KVM_GUESTDBG_ENABLE:        guest debugging is enabled
-  - KVM_GUESTDBG_SINGLESTEP:    the next run should single-step
-
-The top 16 bits of the control field are architecture specific control
-flags which can include the following:
-
-  - KVM_GUESTDBG_USE_SW_BP:     using software breakpoints [x86, arm64]
-  - KVM_GUESTDBG_USE_HW_BP:     using hardware breakpoints [x86, s390, arm64]
-  - KVM_GUESTDBG_INJECT_DB:     inject DB type exception [x86]
-  - KVM_GUESTDBG_INJECT_BP:     inject BP type exception [x86]
-  - KVM_GUESTDBG_EXIT_PENDING:  trigger an immediate guest exit [s390]
-
-For example KVM_GUESTDBG_USE_SW_BP indicates that software breakpoints
-are enabled in memory so we need to ensure breakpoint exceptions are
-correctly trapped and the KVM run loop exits at the breakpoint and not
-running off into the normal guest vector. For KVM_GUESTDBG_USE_HW_BP
-we need to ensure the guest vCPUs architecture specific registers are
-updated to the correct (supplied) values.
-
-The second part of the structure is architecture specific and
-typically contains a set of debug registers.
-
-For arm64 the number of debug registers is implementation defined and
-can be determined by querying the KVM_CAP_GUEST_DEBUG_HW_BPS and
-KVM_CAP_GUEST_DEBUG_HW_WPS capabilities which return a positive number
-indicating the number of supported registers.
-
-When debug events exit the main run loop with the reason
-KVM_EXIT_DEBUG with the kvm_debug_exit_arch part of the kvm_run
-structure containing architecture specific debug information.
-
-4.88 KVM_GET_EMULATED_CPUID
-
-Capability: KVM_CAP_EXT_EMUL_CPUID
-Architectures: x86
-Type: system ioctl
-Parameters: struct kvm_cpuid2 (in/out)
-Returns: 0 on success, -1 on error
-
-struct kvm_cpuid2 {
-       __u32 nent;
-       __u32 flags;
-       struct kvm_cpuid_entry2 entries[0];
-};
-
-The member 'flags' is used for passing flags from userspace.
-
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX                BIT(0)
-#define KVM_CPUID_FLAG_STATEFUL_FUNC           BIT(1)
-#define KVM_CPUID_FLAG_STATE_READ_NEXT         BIT(2)
-
-struct kvm_cpuid_entry2 {
-       __u32 function;
-       __u32 index;
-       __u32 flags;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding[3];
-};
-
-This ioctl returns x86 cpuid features which are emulated by
-kvm.Userspace can use the information returned by this ioctl to query
-which features are emulated by kvm instead of being present natively.
-
-Userspace invokes KVM_GET_EMULATED_CPUID by passing a kvm_cpuid2
-structure with the 'nent' field indicating the number of entries in
-the variable-size array 'entries'. If the number of entries is too low
-to describe the cpu capabilities, an error (E2BIG) is returned. If the
-number is too high, the 'nent' field is adjusted and an error (ENOMEM)
-is returned. If the number is just right, the 'nent' field is adjusted
-to the number of valid entries in the 'entries' array, which is then
-filled.
-
-The entries returned are the set CPUID bits of the respective features
-which kvm emulates, as returned by the CPUID instruction, with unknown
-or unsupported feature bits cleared.
-
-Features like x2apic, for example, may not be present in the host cpu
-but are exposed by kvm in KVM_GET_SUPPORTED_CPUID because they can be
-emulated efficiently and thus not included here.
-
-The fields in each entry are defined as follows:
-
-  function: the eax value used to obtain the entry
-  index: the ecx value used to obtain the entry (for entries that are
-         affected by ecx)
-  flags: an OR of zero or more of the following:
-        KVM_CPUID_FLAG_SIGNIFCANT_INDEX:
-           if the index field is valid
-        KVM_CPUID_FLAG_STATEFUL_FUNC:
-           if cpuid for this function returns different values for successive
-           invocations; there will be several entries with the same function,
-           all with this flag set
-        KVM_CPUID_FLAG_STATE_READ_NEXT:
-           for KVM_CPUID_FLAG_STATEFUL_FUNC entries, set if this entry is
-           the first entry to be read by a cpu
-   eax, ebx, ecx, edx: the values returned by the cpuid instruction for
-         this function/index combination
-
-4.89 KVM_S390_MEM_OP
-
-Capability: KVM_CAP_S390_MEM_OP
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_mem_op (in)
-Returns: = 0 on success,
-         < 0 on generic error (e.g. -EFAULT or -ENOMEM),
-         > 0 if an exception occurred while walking the page tables
-
-Read or write data from/to the logical (virtual) memory of a VCPU.
-
-Parameters are specified via the following structure:
-
-struct kvm_s390_mem_op {
-       __u64 gaddr;            /* the guest address */
-       __u64 flags;            /* flags */
-       __u32 size;             /* amount of bytes */
-       __u32 op;               /* type of operation */
-       __u64 buf;              /* buffer in userspace */
-       __u8 ar;                /* the access register number */
-       __u8 reserved[31];      /* should be set to 0 */
-};
-
-The type of operation is specified in the "op" field. It is either
-KVM_S390_MEMOP_LOGICAL_READ for reading from logical memory space or
-KVM_S390_MEMOP_LOGICAL_WRITE for writing to logical memory space. The
-KVM_S390_MEMOP_F_CHECK_ONLY flag can be set in the "flags" field to check
-whether the corresponding memory access would create an access exception
-(without touching the data in the memory at the destination). In case an
-access exception occurred while walking the MMU tables of the guest, the
-ioctl returns a positive error number to indicate the type of exception.
-This exception is also raised directly at the corresponding VCPU if the
-flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field.
-
-The start address of the memory region has to be specified in the "gaddr"
-field, and the length of the region in the "size" field. "buf" is the buffer
-supplied by the userspace application where the read data should be written
-to for KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written
-is stored for a KVM_S390_MEMOP_LOGICAL_WRITE. "buf" is unused and can be NULL
-when KVM_S390_MEMOP_F_CHECK_ONLY is specified. "ar" designates the access
-register number to be used.
-
-The "reserved" field is meant for future extensions. It is not used by
-KVM with the currently defined set of flags.
-
-4.90 KVM_S390_GET_SKEYS
-
-Capability: KVM_CAP_S390_SKEYS
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_skeys
-Returns: 0 on success, KVM_S390_GET_KEYS_NONE if guest is not using storage
-         keys, negative value on error
-
-This ioctl is used to get guest storage key values on the s390
-architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
-
-struct kvm_s390_skeys {
-       __u64 start_gfn;
-       __u64 count;
-       __u64 skeydata_addr;
-       __u32 flags;
-       __u32 reserved[9];
-};
-
-The start_gfn field is the number of the first guest frame whose storage keys
-you want to get.
-
-The count field is the number of consecutive frames (starting from start_gfn)
-whose storage keys to get. The count field must be at least 1 and the maximum
-allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
-will cause the ioctl to return -EINVAL.
-
-The skeydata_addr field is the address to a buffer large enough to hold count
-bytes. This buffer will be filled with storage key data by the ioctl.
-
-4.91 KVM_S390_SET_SKEYS
-
-Capability: KVM_CAP_S390_SKEYS
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_skeys
-Returns: 0 on success, negative value on error
-
-This ioctl is used to set guest storage key values on the s390
-architecture. The ioctl takes parameters via the kvm_s390_skeys struct.
-See section on KVM_S390_GET_SKEYS for struct definition.
-
-The start_gfn field is the number of the first guest frame whose storage keys
-you want to set.
-
-The count field is the number of consecutive frames (starting from start_gfn)
-whose storage keys to get. The count field must be at least 1 and the maximum
-allowed value is defined as KVM_S390_SKEYS_ALLOC_MAX. Values outside this range
-will cause the ioctl to return -EINVAL.
-
-The skeydata_addr field is the address to a buffer containing count bytes of
-storage keys. Each byte in the buffer will be set as the storage key for a
-single frame starting at start_gfn for count frames.
-
-Note: If any architecturally invalid key value is found in the given data then
-the ioctl will return -EINVAL.
-
-4.92 KVM_S390_IRQ
-
-Capability: KVM_CAP_S390_INJECT_IRQ
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_irq (in)
-Returns: 0 on success, -1 on error
-Errors:
-  EINVAL: interrupt type is invalid
-          type is KVM_S390_SIGP_STOP and flag parameter is invalid value
-          type is KVM_S390_INT_EXTERNAL_CALL and code is bigger
-            than the maximum of VCPUs
-  EBUSY:  type is KVM_S390_SIGP_SET_PREFIX and vcpu is not stopped
-          type is KVM_S390_SIGP_STOP and a stop irq is already pending
-          type is KVM_S390_INT_EXTERNAL_CALL and an external call interrupt
-            is already pending
-
-Allows to inject an interrupt to the guest.
-
-Using struct kvm_s390_irq as a parameter allows
-to inject additional payload which is not
-possible via KVM_S390_INTERRUPT.
-
-Interrupt parameters are passed via kvm_s390_irq:
-
-struct kvm_s390_irq {
-       __u64 type;
-       union {
-               struct kvm_s390_io_info io;
-               struct kvm_s390_ext_info ext;
-               struct kvm_s390_pgm_info pgm;
-               struct kvm_s390_emerg_info emerg;
-               struct kvm_s390_extcall_info extcall;
-               struct kvm_s390_prefix_info prefix;
-               struct kvm_s390_stop_info stop;
-               struct kvm_s390_mchk_info mchk;
-               char reserved[64];
-       } u;
-};
-
-type can be one of the following:
-
-KVM_S390_SIGP_STOP - sigp stop; parameter in .stop
-KVM_S390_PROGRAM_INT - program check; parameters in .pgm
-KVM_S390_SIGP_SET_PREFIX - sigp set prefix; parameters in .prefix
-KVM_S390_RESTART - restart; no parameters
-KVM_S390_INT_CLOCK_COMP - clock comparator interrupt; no parameters
-KVM_S390_INT_CPU_TIMER - CPU timer interrupt; no parameters
-KVM_S390_INT_EMERGENCY - sigp emergency; parameters in .emerg
-KVM_S390_INT_EXTERNAL_CALL - sigp external call; parameters in .extcall
-KVM_S390_MCHK - machine check interrupt; parameters in .mchk
-
-This is an asynchronous vcpu ioctl and can be invoked from any thread.
-
-4.94 KVM_S390_GET_IRQ_STATE
-
-Capability: KVM_CAP_S390_IRQ_STATE
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_irq_state (out)
-Returns: >= number of bytes copied into buffer,
-         -EINVAL if buffer size is 0,
-         -ENOBUFS if buffer size is too small to fit all pending interrupts,
-         -EFAULT if the buffer address was invalid
-
-This ioctl allows userspace to retrieve the complete state of all currently
-pending interrupts in a single buffer. Use cases include migration
-and introspection. The parameter structure contains the address of a
-userspace buffer and its length:
-
-struct kvm_s390_irq_state {
-       __u64 buf;
-       __u32 flags;        /* will stay unused for compatibility reasons */
-       __u32 len;
-       __u32 reserved[4];  /* will stay unused for compatibility reasons */
-};
-
-Userspace passes in the above struct and for each pending interrupt a
-struct kvm_s390_irq is copied to the provided buffer.
-
-The structure contains a flags and a reserved field for future extensions. As
-the kernel never checked for flags == 0 and QEMU never pre-zeroed flags and
-reserved, these fields can not be used in the future without breaking
-compatibility.
-
-If -ENOBUFS is returned the buffer provided was too small and userspace
-may retry with a bigger buffer.
-
-4.95 KVM_S390_SET_IRQ_STATE
-
-Capability: KVM_CAP_S390_IRQ_STATE
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_irq_state (in)
-Returns: 0 on success,
-         -EFAULT if the buffer address was invalid,
-         -EINVAL for an invalid buffer length (see below),
-         -EBUSY if there were already interrupts pending,
-         errors occurring when actually injecting the
-          interrupt. See KVM_S390_IRQ.
-
-This ioctl allows userspace to set the complete state of all cpu-local
-interrupts currently pending for the vcpu. It is intended for restoring
-interrupt state after a migration. The input parameter is a userspace buffer
-containing a struct kvm_s390_irq_state:
-
-struct kvm_s390_irq_state {
-       __u64 buf;
-       __u32 flags;        /* will stay unused for compatibility reasons */
-       __u32 len;
-       __u32 reserved[4];  /* will stay unused for compatibility reasons */
-};
-
-The restrictions for flags and reserved apply as well.
-(see KVM_S390_GET_IRQ_STATE)
-
-The userspace memory referenced by buf contains a struct kvm_s390_irq
-for each interrupt to be injected into the guest.
-If one of the interrupts could not be injected for some reason the
-ioctl aborts.
-
-len must be a multiple of sizeof(struct kvm_s390_irq). It must be > 0
-and it must not exceed (max_vcpus + 32) * sizeof(struct kvm_s390_irq),
-which is the maximum number of possibly pending cpu-local interrupts.
-
-4.96 KVM_SMI
-
-Capability: KVM_CAP_X86_SMM
-Architectures: x86
-Type: vcpu ioctl
-Parameters: none
-Returns: 0 on success, -1 on error
-
-Queues an SMI on the thread's vcpu.
-
-4.97 KVM_CAP_PPC_MULTITCE
-
-Capability: KVM_CAP_PPC_MULTITCE
-Architectures: ppc
-Type: vm
-
-This capability means the kernel is capable of handling hypercalls
-H_PUT_TCE_INDIRECT and H_STUFF_TCE without passing those into the user
-space. This significantly accelerates DMA operations for PPC KVM guests.
-User space should expect that its handlers for these hypercalls
-are not going to be called if user space previously registered LIOBN
-in KVM (via KVM_CREATE_SPAPR_TCE or similar calls).
-
-In order to enable H_PUT_TCE_INDIRECT and H_STUFF_TCE use in the guest,
-user space might have to advertise it for the guest. For example,
-IBM pSeries (sPAPR) guest starts using them if "hcall-multi-tce" is
-present in the "ibm,hypertas-functions" device-tree property.
-
-The hypercalls mentioned above may or may not be processed successfully
-in the kernel based fast path. If they can not be handled by the kernel,
-they will get passed on to user space. So user space still has to have
-an implementation for these despite the in kernel acceleration.
-
-This capability is always enabled.
-
-4.98 KVM_CREATE_SPAPR_TCE_64
-
-Capability: KVM_CAP_SPAPR_TCE_64
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_create_spapr_tce_64 (in)
-Returns: file descriptor for manipulating the created TCE table
-
-This is an extension for KVM_CAP_SPAPR_TCE which only supports 32bit
-windows, described in 4.62 KVM_CREATE_SPAPR_TCE
-
-This capability uses extended struct in ioctl interface:
-
-/* for KVM_CAP_SPAPR_TCE_64 */
-struct kvm_create_spapr_tce_64 {
-       __u64 liobn;
-       __u32 page_shift;
-       __u32 flags;
-       __u64 offset;   /* in pages */
-       __u64 size;     /* in pages */
-};
-
-The aim of extension is to support an additional bigger DMA window with
-a variable page size.
-KVM_CREATE_SPAPR_TCE_64 receives a 64bit window size, an IOMMU page shift and
-a bus offset of the corresponding DMA window, @size and @offset are numbers
-of IOMMU pages.
-
-@flags are not used at the moment.
-
-The rest of functionality is identical to KVM_CREATE_SPAPR_TCE.
-
-4.99 KVM_REINJECT_CONTROL
-
-Capability: KVM_CAP_REINJECT_CONTROL
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_reinject_control (in)
-Returns: 0 on success,
-         -EFAULT if struct kvm_reinject_control cannot be read,
-         -ENXIO if KVM_CREATE_PIT or KVM_CREATE_PIT2 didn't succeed earlier.
-
-i8254 (PIT) has two modes, reinject and !reinject.  The default is reinject,
-where KVM queues elapsed i8254 ticks and monitors completion of interrupt from
-vector(s) that i8254 injects.  Reinject mode dequeues a tick and injects its
-interrupt whenever there isn't a pending interrupt from i8254.
-!reinject mode injects an interrupt as soon as a tick arrives.
-
-struct kvm_reinject_control {
-       __u8 pit_reinject;
-       __u8 reserved[31];
-};
-
-pit_reinject = 0 (!reinject mode) is recommended, unless running an old
-operating system that uses the PIT for timing (e.g. Linux 2.4.x).
-
-4.100 KVM_PPC_CONFIGURE_V3_MMU
-
-Capability: KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_ppc_mmuv3_cfg (in)
-Returns: 0 on success,
-         -EFAULT if struct kvm_ppc_mmuv3_cfg cannot be read,
-         -EINVAL if the configuration is invalid
-
-This ioctl controls whether the guest will use radix or HPT (hashed
-page table) translation, and sets the pointer to the process table for
-the guest.
-
-struct kvm_ppc_mmuv3_cfg {
-       __u64   flags;
-       __u64   process_table;
-};
-
-There are two bits that can be set in flags; KVM_PPC_MMUV3_RADIX and
-KVM_PPC_MMUV3_GTSE.  KVM_PPC_MMUV3_RADIX, if set, configures the guest
-to use radix tree translation, and if clear, to use HPT translation.
-KVM_PPC_MMUV3_GTSE, if set and if KVM permits it, configures the guest
-to be able to use the global TLB and SLB invalidation instructions;
-if clear, the guest may not use these instructions.
-
-The process_table field specifies the address and size of the guest
-process table, which is in the guest's space.  This field is formatted
-as the second doubleword of the partition table entry, as defined in
-the Power ISA V3.00, Book III section 5.7.6.1.
-
-4.101 KVM_PPC_GET_RMMU_INFO
-
-Capability: KVM_CAP_PPC_RADIX_MMU
-Architectures: ppc
-Type: vm ioctl
-Parameters: struct kvm_ppc_rmmu_info (out)
-Returns: 0 on success,
-        -EFAULT if struct kvm_ppc_rmmu_info cannot be written,
-        -EINVAL if no useful information can be returned
-
-This ioctl returns a structure containing two things: (a) a list
-containing supported radix tree geometries, and (b) a list that maps
-page sizes to put in the "AP" (actual page size) field for the tlbie
-(TLB invalidate entry) instruction.
-
-struct kvm_ppc_rmmu_info {
-       struct kvm_ppc_radix_geom {
-               __u8    page_shift;
-               __u8    level_bits[4];
-               __u8    pad[3];
-       }       geometries[8];
-       __u32   ap_encodings[8];
-};
-
-The geometries[] field gives up to 8 supported geometries for the
-radix page table, in terms of the log base 2 of the smallest page
-size, and the number of bits indexed at each level of the tree, from
-the PTE level up to the PGD level in that order.  Any unused entries
-will have 0 in the page_shift field.
-
-The ap_encodings gives the supported page sizes and their AP field
-encodings, encoded with the AP value in the top 3 bits and the log
-base 2 of the page size in the bottom 6 bits.
-
-4.102 KVM_PPC_RESIZE_HPT_PREPARE
-
-Capability: KVM_CAP_SPAPR_RESIZE_HPT
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_ppc_resize_hpt (in)
-Returns: 0 on successful completion,
-        >0 if a new HPT is being prepared, the value is an estimated
-             number of milliseconds until preparation is complete
-         -EFAULT if struct kvm_reinject_control cannot be read,
-        -EINVAL if the supplied shift or flags are invalid
-        -ENOMEM if unable to allocate the new HPT
-        -ENOSPC if there was a hash collision when moving existing
-                  HPT entries to the new HPT
-        -EIO on other error conditions
-
-Used to implement the PAPR extension for runtime resizing of a guest's
-Hashed Page Table (HPT).  Specifically this starts, stops or monitors
-the preparation of a new potential HPT for the guest, essentially
-implementing the H_RESIZE_HPT_PREPARE hypercall.
-
-If called with shift > 0 when there is no pending HPT for the guest,
-this begins preparation of a new pending HPT of size 2^(shift) bytes.
-It then returns a positive integer with the estimated number of
-milliseconds until preparation is complete.
-
-If called when there is a pending HPT whose size does not match that
-requested in the parameters, discards the existing pending HPT and
-creates a new one as above.
-
-If called when there is a pending HPT of the size requested, will:
-  * If preparation of the pending HPT is already complete, return 0
-  * If preparation of the pending HPT has failed, return an error
-    code, then discard the pending HPT.
-  * If preparation of the pending HPT is still in progress, return an
-    estimated number of milliseconds until preparation is complete.
-
-If called with shift == 0, discards any currently pending HPT and
-returns 0 (i.e. cancels any in-progress preparation).
-
-flags is reserved for future expansion, currently setting any bits in
-flags will result in an -EINVAL.
-
-Normally this will be called repeatedly with the same parameters until
-it returns <= 0.  The first call will initiate preparation, subsequent
-ones will monitor preparation until it completes or fails.
-
-struct kvm_ppc_resize_hpt {
-       __u64 flags;
-       __u32 shift;
-       __u32 pad;
-};
-
-4.103 KVM_PPC_RESIZE_HPT_COMMIT
-
-Capability: KVM_CAP_SPAPR_RESIZE_HPT
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_ppc_resize_hpt (in)
-Returns: 0 on successful completion,
-         -EFAULT if struct kvm_reinject_control cannot be read,
-        -EINVAL if the supplied shift or flags are invalid
-        -ENXIO is there is no pending HPT, or the pending HPT doesn't
-                 have the requested size
-        -EBUSY if the pending HPT is not fully prepared
-        -ENOSPC if there was a hash collision when moving existing
-                  HPT entries to the new HPT
-        -EIO on other error conditions
-
-Used to implement the PAPR extension for runtime resizing of a guest's
-Hashed Page Table (HPT).  Specifically this requests that the guest be
-transferred to working with the new HPT, essentially implementing the
-H_RESIZE_HPT_COMMIT hypercall.
-
-This should only be called after KVM_PPC_RESIZE_HPT_PREPARE has
-returned 0 with the same parameters.  In other cases
-KVM_PPC_RESIZE_HPT_COMMIT will return an error (usually -ENXIO or
--EBUSY, though others may be possible if the preparation was started,
-but failed).
-
-This will have undefined effects on the guest if it has not already
-placed itself in a quiescent state where no vcpu will make MMU enabled
-memory accesses.
-
-On succsful completion, the pending HPT will become the guest's active
-HPT and the previous HPT will be discarded.
-
-On failure, the guest will still be operating on its previous HPT.
-
-struct kvm_ppc_resize_hpt {
-       __u64 flags;
-       __u32 shift;
-       __u32 pad;
-};
-
-4.104 KVM_X86_GET_MCE_CAP_SUPPORTED
-
-Capability: KVM_CAP_MCE
-Architectures: x86
-Type: system ioctl
-Parameters: u64 mce_cap (out)
-Returns: 0 on success, -1 on error
-
-Returns supported MCE capabilities. The u64 mce_cap parameter
-has the same format as the MSR_IA32_MCG_CAP register. Supported
-capabilities will have the corresponding bits set.
-
-4.105 KVM_X86_SETUP_MCE
-
-Capability: KVM_CAP_MCE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: u64 mcg_cap (in)
-Returns: 0 on success,
-         -EFAULT if u64 mcg_cap cannot be read,
-         -EINVAL if the requested number of banks is invalid,
-         -EINVAL if requested MCE capability is not supported.
-
-Initializes MCE support for use. The u64 mcg_cap parameter
-has the same format as the MSR_IA32_MCG_CAP register and
-specifies which capabilities should be enabled. The maximum
-supported number of error-reporting banks can be retrieved when
-checking for KVM_CAP_MCE. The supported capabilities can be
-retrieved with KVM_X86_GET_MCE_CAP_SUPPORTED.
-
-4.106 KVM_X86_SET_MCE
-
-Capability: KVM_CAP_MCE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_x86_mce (in)
-Returns: 0 on success,
-         -EFAULT if struct kvm_x86_mce cannot be read,
-         -EINVAL if the bank number is invalid,
-         -EINVAL if VAL bit is not set in status field.
-
-Inject a machine check error (MCE) into the guest. The input
-parameter is:
-
-struct kvm_x86_mce {
-       __u64 status;
-       __u64 addr;
-       __u64 misc;
-       __u64 mcg_status;
-       __u8 bank;
-       __u8 pad1[7];
-       __u64 pad2[3];
-};
-
-If the MCE being reported is an uncorrected error, KVM will
-inject it as an MCE exception into the guest. If the guest
-MCG_STATUS register reports that an MCE is in progress, KVM
-causes an KVM_EXIT_SHUTDOWN vmexit.
-
-Otherwise, if the MCE is a corrected error, KVM will just
-store it in the corresponding bank (provided this bank is
-not holding a previously reported uncorrected error).
-
-4.107 KVM_S390_GET_CMMA_BITS
-
-Capability: KVM_CAP_S390_CMMA_MIGRATION
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_cmma_log (in, out)
-Returns: 0 on success, a negative value on error
-
-This ioctl is used to get the values of the CMMA bits on the s390
-architecture. It is meant to be used in two scenarios:
-- During live migration to save the CMMA values. Live migration needs
-  to be enabled via the KVM_REQ_START_MIGRATION VM property.
-- To non-destructively peek at the CMMA values, with the flag
-  KVM_S390_CMMA_PEEK set.
-
-The ioctl takes parameters via the kvm_s390_cmma_log struct. The desired
-values are written to a buffer whose location is indicated via the "values"
-member in the kvm_s390_cmma_log struct.  The values in the input struct are
-also updated as needed.
-Each CMMA value takes up one byte.
-
-struct kvm_s390_cmma_log {
-       __u64 start_gfn;
-       __u32 count;
-       __u32 flags;
-       union {
-               __u64 remaining;
-               __u64 mask;
-       };
-       __u64 values;
-};
-
-start_gfn is the number of the first guest frame whose CMMA values are
-to be retrieved,
-
-count is the length of the buffer in bytes,
-
-values points to the buffer where the result will be written to.
-
-If count is greater than KVM_S390_SKEYS_MAX, then it is considered to be
-KVM_S390_SKEYS_MAX. KVM_S390_SKEYS_MAX is re-used for consistency with
-other ioctls.
-
-The result is written in the buffer pointed to by the field values, and
-the values of the input parameter are updated as follows.
-
-Depending on the flags, different actions are performed. The only
-supported flag so far is KVM_S390_CMMA_PEEK.
-
-The default behaviour if KVM_S390_CMMA_PEEK is not set is:
-start_gfn will indicate the first page frame whose CMMA bits were dirty.
-It is not necessarily the same as the one passed as input, as clean pages
-are skipped.
-
-count will indicate the number of bytes actually written in the buffer.
-It can (and very often will) be smaller than the input value, since the
-buffer is only filled until 16 bytes of clean values are found (which
-are then not copied in the buffer). Since a CMMA migration block needs
-the base address and the length, for a total of 16 bytes, we will send
-back some clean data if there is some dirty data afterwards, as long as
-the size of the clean data does not exceed the size of the header. This
-allows to minimize the amount of data to be saved or transferred over
-the network at the expense of more roundtrips to userspace. The next
-invocation of the ioctl will skip over all the clean values, saving
-potentially more than just the 16 bytes we found.
-
-If KVM_S390_CMMA_PEEK is set:
-the existing storage attributes are read even when not in migration
-mode, and no other action is performed;
-
-the output start_gfn will be equal to the input start_gfn,
-
-the output count will be equal to the input count, except if the end of
-memory has been reached.
-
-In both cases:
-the field "remaining" will indicate the total number of dirty CMMA values
-still remaining, or 0 if KVM_S390_CMMA_PEEK is set and migration mode is
-not enabled.
-
-mask is unused.
-
-values points to the userspace buffer where the result will be stored.
-
-This ioctl can fail with -ENOMEM if not enough memory can be allocated to
-complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
-KVM_S390_CMMA_PEEK is not set but migration mode was not enabled, with
--EFAULT if the userspace address is invalid or if no page table is
-present for the addresses (e.g. when using hugepages).
-
-4.108 KVM_S390_SET_CMMA_BITS
-
-Capability: KVM_CAP_S390_CMMA_MIGRATION
-Architectures: s390
-Type: vm ioctl
-Parameters: struct kvm_s390_cmma_log (in)
-Returns: 0 on success, a negative value on error
-
-This ioctl is used to set the values of the CMMA bits on the s390
-architecture. It is meant to be used during live migration to restore
-the CMMA values, but there are no restrictions on its use.
-The ioctl takes parameters via the kvm_s390_cmma_values struct.
-Each CMMA value takes up one byte.
-
-struct kvm_s390_cmma_log {
-       __u64 start_gfn;
-       __u32 count;
-       __u32 flags;
-       union {
-               __u64 remaining;
-               __u64 mask;
-       };
-       __u64 values;
-};
-
-start_gfn indicates the starting guest frame number,
-
-count indicates how many values are to be considered in the buffer,
-
-flags is not used and must be 0.
-
-mask indicates which PGSTE bits are to be considered.
-
-remaining is not used.
-
-values points to the buffer in userspace where to store the values.
-
-This ioctl can fail with -ENOMEM if not enough memory can be allocated to
-complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
-the count field is too large (e.g. more than KVM_S390_CMMA_SIZE_MAX) or
-if the flags field was not 0, with -EFAULT if the userspace address is
-invalid, if invalid pages are written to (e.g. after the end of memory)
-or if no page table is present for the addresses (e.g. when using
-hugepages).
-
-4.109 KVM_PPC_GET_CPU_CHAR
-
-Capability: KVM_CAP_PPC_GET_CPU_CHAR
-Architectures: powerpc
-Type: vm ioctl
-Parameters: struct kvm_ppc_cpu_char (out)
-Returns: 0 on successful completion
-        -EFAULT if struct kvm_ppc_cpu_char cannot be written
-
-This ioctl gives userspace information about certain characteristics
-of the CPU relating to speculative execution of instructions and
-possible information leakage resulting from speculative execution (see
-CVE-2017-5715, CVE-2017-5753 and CVE-2017-5754).  The information is
-returned in struct kvm_ppc_cpu_char, which looks like this:
-
-struct kvm_ppc_cpu_char {
-       __u64   character;              /* characteristics of the CPU */
-       __u64   behaviour;              /* recommended software behaviour */
-       __u64   character_mask;         /* valid bits in character */
-       __u64   behaviour_mask;         /* valid bits in behaviour */
-};
-
-For extensibility, the character_mask and behaviour_mask fields
-indicate which bits of character and behaviour have been filled in by
-the kernel.  If the set of defined bits is extended in future then
-userspace will be able to tell whether it is running on a kernel that
-knows about the new bits.
-
-The character field describes attributes of the CPU which can help
-with preventing inadvertent information disclosure - specifically,
-whether there is an instruction to flash-invalidate the L1 data cache
-(ori 30,30,0 or mtspr SPRN_TRIG2,rN), whether the L1 data cache is set
-to a mode where entries can only be used by the thread that created
-them, whether the bcctr[l] instruction prevents speculation, and
-whether a speculation barrier instruction (ori 31,31,0) is provided.
-
-The behaviour field describes actions that software should take to
-prevent inadvertent information disclosure, and thus describes which
-vulnerabilities the hardware is subject to; specifically whether the
-L1 data cache should be flushed when returning to user mode from the
-kernel, and whether a speculation barrier should be placed between an
-array bounds check and the array access.
-
-These fields use the same bit definitions as the new
-H_GET_CPU_CHARACTERISTICS hypercall.
-
-4.110 KVM_MEMORY_ENCRYPT_OP
-
-Capability: basic
-Architectures: x86
-Type: system
-Parameters: an opaque platform specific structure (in/out)
-Returns: 0 on success; -1 on error
-
-If the platform supports creating encrypted VMs then this ioctl can be used
-for issuing platform-specific memory encryption commands to manage those
-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.
-
-4.111 KVM_MEMORY_ENCRYPT_REG_REGION
-
-Capability: basic
-Architectures: x86
-Type: system
-Parameters: struct kvm_enc_region (in)
-Returns: 0 on success; -1 on error
-
-This ioctl can be used to register a guest memory region which may
-contain encrypted data (e.g. guest RAM, SMRAM etc).
-
-It is used in the SEV-enabled guest. When encryption is enabled, a guest
-memory region may contain encrypted data. The SEV memory encryption
-engine uses a tweak such that two identical plaintext pages, each at
-different locations will have differing ciphertexts. So swapping or
-moving ciphertext of those pages will not result in plaintext being
-swapped. So relocating (or migrating) physical backing pages for the SEV
-guest will require some additional steps.
-
-Note: The current SEV key management spec does not provide commands to
-swap or migrate (move) ciphertext pages. Hence, for now we pin the guest
-memory region registered with the ioctl.
-
-4.112 KVM_MEMORY_ENCRYPT_UNREG_REGION
-
-Capability: basic
-Architectures: x86
-Type: system
-Parameters: struct kvm_enc_region (in)
-Returns: 0 on success; -1 on error
-
-This ioctl can be used to unregister the guest memory region registered
-with KVM_MEMORY_ENCRYPT_REG_REGION ioctl above.
-
-4.113 KVM_HYPERV_EVENTFD
-
-Capability: KVM_CAP_HYPERV_EVENTFD
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_hyperv_eventfd (in)
-
-This ioctl (un)registers an eventfd to receive notifications from the guest on
-the specified Hyper-V connection id through the SIGNAL_EVENT hypercall, without
-causing a user exit.  SIGNAL_EVENT hypercall with non-zero event flag number
-(bits 24-31) still triggers a KVM_EXIT_HYPERV_HCALL user exit.
-
-struct kvm_hyperv_eventfd {
-       __u32 conn_id;
-       __s32 fd;
-       __u32 flags;
-       __u32 padding[3];
-};
-
-The conn_id field should fit within 24 bits:
-
-#define KVM_HYPERV_CONN_ID_MASK                0x00ffffff
-
-The acceptable values for the flags field are:
-
-#define KVM_HYPERV_EVENTFD_DEASSIGN    (1 << 0)
-
-Returns: 0 on success,
-       -EINVAL if conn_id or flags is outside the allowed range
-       -ENOENT on deassign if the conn_id isn't registered
-       -EEXIST on assign if the conn_id is already registered
-
-4.114 KVM_GET_NESTED_STATE
-
-Capability: KVM_CAP_NESTED_STATE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_nested_state (in/out)
-Returns: 0 on success, -1 on error
-Errors:
-  E2BIG:     the total state size exceeds the value of 'size' specified by
-             the user; the size required will be written into size.
-
-struct kvm_nested_state {
-       __u16 flags;
-       __u16 format;
-       __u32 size;
-
-       union {
-               struct kvm_vmx_nested_state_hdr vmx;
-               struct kvm_svm_nested_state_hdr svm;
-
-               /* Pad the header to 128 bytes.  */
-               __u8 pad[120];
-       } hdr;
-
-       union {
-               struct kvm_vmx_nested_state_data vmx[0];
-               struct kvm_svm_nested_state_data svm[0];
-       } data;
-};
-
-#define KVM_STATE_NESTED_GUEST_MODE    0x00000001
-#define KVM_STATE_NESTED_RUN_PENDING   0x00000002
-#define KVM_STATE_NESTED_EVMCS         0x00000004
-
-#define KVM_STATE_NESTED_FORMAT_VMX            0
-#define KVM_STATE_NESTED_FORMAT_SVM            1
-
-#define KVM_STATE_NESTED_VMX_VMCS_SIZE         0x1000
-
-#define KVM_STATE_NESTED_VMX_SMM_GUEST_MODE    0x00000001
-#define KVM_STATE_NESTED_VMX_SMM_VMXON         0x00000002
-
-struct kvm_vmx_nested_state_hdr {
-       __u64 vmxon_pa;
-       __u64 vmcs12_pa;
-
-       struct {
-               __u16 flags;
-       } smm;
-};
-
-struct kvm_vmx_nested_state_data {
-       __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
-       __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
-};
-
-This ioctl copies the vcpu's nested virtualization state from the kernel to
-userspace.
-
-The maximum size of the state can be retrieved by passing KVM_CAP_NESTED_STATE
-to the KVM_CHECK_EXTENSION ioctl().
-
-4.115 KVM_SET_NESTED_STATE
-
-Capability: KVM_CAP_NESTED_STATE
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_nested_state (in)
-Returns: 0 on success, -1 on error
-
-This copies the vcpu's kvm_nested_state struct from userspace to the kernel.
-For the definition of struct kvm_nested_state, see KVM_GET_NESTED_STATE.
-
-4.116 KVM_(UN)REGISTER_COALESCED_MMIO
-
-Capability: KVM_CAP_COALESCED_MMIO (for coalesced mmio)
-           KVM_CAP_COALESCED_PIO (for coalesced pio)
-Architectures: all
-Type: vm ioctl
-Parameters: struct kvm_coalesced_mmio_zone
-Returns: 0 on success, < 0 on error
-
-Coalesced I/O is a performance optimization that defers hardware
-register write emulation so that userspace exits are avoided.  It is
-typically used to reduce the overhead of emulating frequently accessed
-hardware registers.
-
-When a hardware register is configured for coalesced I/O, write accesses
-do not exit to userspace and their value is recorded in a ring buffer
-that is shared between kernel and userspace.
-
-Coalesced I/O is used if one or more write accesses to a hardware
-register can be deferred until a read or a write to another hardware
-register on the same device.  This last access will cause a vmexit and
-userspace will process accesses from the ring buffer before emulating
-it. That will avoid exiting to userspace on repeated writes.
-
-Coalesced pio is based on coalesced mmio. There is little difference
-between coalesced mmio and pio except that coalesced pio records accesses
-to I/O ports.
-
-4.117 KVM_CLEAR_DIRTY_LOG (vm ioctl)
-
-Capability: KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
-Architectures: x86, arm, arm64, mips
-Type: vm ioctl
-Parameters: struct kvm_dirty_log (in)
-Returns: 0 on success, -1 on error
-
-/* for KVM_CLEAR_DIRTY_LOG */
-struct kvm_clear_dirty_log {
-       __u32 slot;
-       __u32 num_pages;
-       __u64 first_page;
-       union {
-               void __user *dirty_bitmap; /* one bit per page */
-               __u64 padding;
-       };
-};
-
-The ioctl clears the dirty status of pages in a memory slot, according to
-the bitmap that is passed in struct kvm_clear_dirty_log's dirty_bitmap
-field.  Bit 0 of the bitmap corresponds to page "first_page" in the
-memory slot, and num_pages is the size in bits of the input bitmap.
-first_page must be a multiple of 64; num_pages must also be a multiple of
-64 unless first_page + num_pages is the size of the memory slot.  For each
-bit that is set in the input bitmap, the corresponding page is marked "clean"
-in KVM's dirty bitmap, and dirty tracking is re-enabled for that page
-(for example via write-protection, or by clearing the dirty bit in
-a page table entry).
-
-If KVM_CAP_MULTI_ADDRESS_SPACE is available, bits 16-31 specifies
-the address space for which you want to return the dirty bitmap.
-They must be less than the value that KVM_CHECK_EXTENSION returns for
-the KVM_CAP_MULTI_ADDRESS_SPACE capability.
-
-This ioctl is mostly useful when KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
-is enabled; for more information, see the description of the capability.
-However, it can always be used as long as KVM_CHECK_EXTENSION confirms
-that KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is present.
-
-4.118 KVM_GET_SUPPORTED_HV_CPUID
-
-Capability: KVM_CAP_HYPERV_CPUID
-Architectures: x86
-Type: vcpu ioctl
-Parameters: struct kvm_cpuid2 (in/out)
-Returns: 0 on success, -1 on error
-
-struct kvm_cpuid2 {
-       __u32 nent;
-       __u32 padding;
-       struct kvm_cpuid_entry2 entries[0];
-};
-
-struct kvm_cpuid_entry2 {
-       __u32 function;
-       __u32 index;
-       __u32 flags;
-       __u32 eax;
-       __u32 ebx;
-       __u32 ecx;
-       __u32 edx;
-       __u32 padding[3];
-};
-
-This ioctl returns x86 cpuid features leaves related to Hyper-V emulation in
-KVM.  Userspace can use the information returned by this ioctl to construct
-cpuid information presented to guests consuming Hyper-V enlightenments (e.g.
-Windows or Hyper-V guests).
-
-CPUID feature leaves returned by this ioctl are defined by Hyper-V Top Level
-Functional Specification (TLFS). These leaves can't be obtained with
-KVM_GET_SUPPORTED_CPUID ioctl because some of them intersect with KVM feature
-leaves (0x40000000, 0x40000001).
-
-Currently, the following list of CPUID leaves are returned:
- HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS
- HYPERV_CPUID_INTERFACE
- HYPERV_CPUID_VERSION
- HYPERV_CPUID_FEATURES
- HYPERV_CPUID_ENLIGHTMENT_INFO
- HYPERV_CPUID_IMPLEMENT_LIMITS
- HYPERV_CPUID_NESTED_FEATURES
-
-HYPERV_CPUID_NESTED_FEATURES leaf is only exposed when Enlightened VMCS was
-enabled on the corresponding vCPU (KVM_CAP_HYPERV_ENLIGHTENED_VMCS).
-
-Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
-with the 'nent' field indicating the number of entries in the variable-size
-array 'entries'.  If the number of entries is too low to describe all Hyper-V
-feature leaves, an error (E2BIG) is returned. If the number is more or equal
-to the number of Hyper-V feature leaves, the 'nent' field is adjusted to the
-number of valid entries in the 'entries' array, which is then filled.
-
-'index' and 'flags' fields in 'struct kvm_cpuid_entry2' are currently reserved,
-userspace should not expect to get any particular value there.
-
-4.119 KVM_ARM_VCPU_FINALIZE
-
-Architectures: arm, arm64
-Type: vcpu ioctl
-Parameters: int feature (in)
-Returns: 0 on success, -1 on error
-Errors:
-  EPERM:     feature not enabled, needs configuration, or already finalized
-  EINVAL:    feature unknown or not present
-
-Recognised values for feature:
-  arm64      KVM_ARM_VCPU_SVE (requires KVM_CAP_ARM_SVE)
-
-Finalizes the configuration of the specified vcpu feature.
-
-The vcpu must already have been initialised, enabling the affected feature, by
-means of a successful KVM_ARM_VCPU_INIT call with the appropriate flag set in
-features[].
-
-For affected vcpu features, this is a mandatory step that must be performed
-before the vcpu is fully usable.
-
-Between KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE, the feature may be
-configured by use of ioctls such as KVM_SET_ONE_REG.  The exact configuration
-that should be performaned and how to do it are feature-dependent.
-
-Other calls that depend on a particular feature being finalized, such as
-KVM_RUN, KVM_GET_REG_LIST, KVM_GET_ONE_REG and KVM_SET_ONE_REG, will fail with
--EPERM unless the feature has already been finalized by means of a
-KVM_ARM_VCPU_FINALIZE call.
-
-See KVM_ARM_VCPU_INIT for details of vcpu features that require finalization
-using this ioctl.
-
-4.120 KVM_SET_PMU_EVENT_FILTER
-
-Capability: KVM_CAP_PMU_EVENT_FILTER
-Architectures: x86
-Type: vm ioctl
-Parameters: struct kvm_pmu_event_filter (in)
-Returns: 0 on success, -1 on error
-
-struct kvm_pmu_event_filter {
-       __u32 action;
-       __u32 nevents;
-       __u32 fixed_counter_bitmap;
-       __u32 flags;
-       __u32 pad[4];
-       __u64 events[0];
-};
-
-This ioctl restricts the set of PMU events that the guest can program.
-The argument holds a list of events which will be allowed or denied.
-The eventsel+umask of each event the guest attempts to program is compared
-against the events field to determine whether the guest should have access.
-The events field only controls general purpose counters; fixed purpose
-counters are controlled by the fixed_counter_bitmap.
-
-No flags are defined yet, the field must be zero.
-
-Valid values for 'action':
-#define KVM_PMU_EVENT_ALLOW 0
-#define KVM_PMU_EVENT_DENY 1
-
-
-5. The kvm_run structure
-------------------------
-
-Application code obtains a pointer to the kvm_run structure by
-mmap()ing a vcpu fd.  From that point, application code can control
-execution by changing fields in kvm_run prior to calling the KVM_RUN
-ioctl, and obtain information about the reason KVM_RUN returned by
-looking up structure members.
-
-struct kvm_run {
-       /* in */
-       __u8 request_interrupt_window;
-
-Request that KVM_RUN return when it becomes possible to inject external
-interrupts into the guest.  Useful in conjunction with KVM_INTERRUPT.
-
-       __u8 immediate_exit;
-
-This field is polled once when KVM_RUN starts; if non-zero, KVM_RUN
-exits immediately, returning -EINTR.  In the common scenario where a
-signal is used to "kick" a VCPU out of KVM_RUN, this field can be used
-to avoid usage of KVM_SET_SIGNAL_MASK, which has worse scalability.
-Rather than blocking the signal outside KVM_RUN, userspace can set up
-a signal handler that sets run->immediate_exit to a non-zero value.
-
-This field is ignored if KVM_CAP_IMMEDIATE_EXIT is not available.
-
-       __u8 padding1[6];
-
-       /* out */
-       __u32 exit_reason;
-
-When KVM_RUN has returned successfully (return value 0), this informs
-application code why KVM_RUN has returned.  Allowable values for this
-field are detailed below.
-
-       __u8 ready_for_interrupt_injection;
-
-If request_interrupt_window has been specified, this field indicates
-an interrupt can be injected now with KVM_INTERRUPT.
-
-       __u8 if_flag;
-
-The value of the current interrupt flag.  Only valid if in-kernel
-local APIC is not used.
-
-       __u16 flags;
-
-More architecture-specific flags detailing state of the VCPU that may
-affect the device's behavior.  The only currently defined flag is
-KVM_RUN_X86_SMM, which is valid on x86 machines and is set if the
-VCPU is in system management mode.
-
-       /* in (pre_kvm_run), out (post_kvm_run) */
-       __u64 cr8;
-
-The value of the cr8 register.  Only valid if in-kernel local APIC is
-not used.  Both input and output.
-
-       __u64 apic_base;
-
-The value of the APIC BASE msr.  Only valid if in-kernel local
-APIC is not used.  Both input and output.
-
-       union {
-               /* KVM_EXIT_UNKNOWN */
-               struct {
-                       __u64 hardware_exit_reason;
-               } hw;
-
-If exit_reason is KVM_EXIT_UNKNOWN, the vcpu has exited due to unknown
-reasons.  Further architecture-specific information is available in
-hardware_exit_reason.
-
-               /* KVM_EXIT_FAIL_ENTRY */
-               struct {
-                       __u64 hardware_entry_failure_reason;
-               } fail_entry;
-
-If exit_reason is KVM_EXIT_FAIL_ENTRY, the vcpu could not be run due
-to unknown reasons.  Further architecture-specific information is
-available in hardware_entry_failure_reason.
-
-               /* KVM_EXIT_EXCEPTION */
-               struct {
-                       __u32 exception;
-                       __u32 error_code;
-               } ex;
-
-Unused.
-
-               /* KVM_EXIT_IO */
-               struct {
-#define KVM_EXIT_IO_IN  0
-#define KVM_EXIT_IO_OUT 1
-                       __u8 direction;
-                       __u8 size; /* bytes */
-                       __u16 port;
-                       __u32 count;
-                       __u64 data_offset; /* relative to kvm_run start */
-               } io;
-
-If exit_reason is KVM_EXIT_IO, then the vcpu has
-executed a port I/O instruction which could not be satisfied by kvm.
-data_offset describes where the data is located (KVM_EXIT_IO_OUT) or
-where kvm expects application code to place the data for the next
-KVM_RUN invocation (KVM_EXIT_IO_IN).  Data format is a packed array.
-
-               /* KVM_EXIT_DEBUG */
-               struct {
-                       struct kvm_debug_exit_arch arch;
-               } debug;
-
-If the exit_reason is KVM_EXIT_DEBUG, then a vcpu is processing a debug event
-for which architecture specific information is returned.
-
-               /* KVM_EXIT_MMIO */
-               struct {
-                       __u64 phys_addr;
-                       __u8  data[8];
-                       __u32 len;
-                       __u8  is_write;
-               } mmio;
-
-If exit_reason is KVM_EXIT_MMIO, then the vcpu has
-executed a memory-mapped I/O instruction which could not be satisfied
-by kvm.  The 'data' member contains the written data if 'is_write' is
-true, and should be filled by application code otherwise.
-
-The 'data' member contains, in its first 'len' bytes, the value as it would
-appear if the VCPU performed a load or store of the appropriate width directly
-to the byte array.
-
-NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR and
-      KVM_EXIT_EPR the corresponding
-operations are complete (and guest state is consistent) only after userspace
-has re-entered the kernel with KVM_RUN.  The kernel side will first finish
-incomplete operations and then check for pending signals.  Userspace
-can re-enter the guest with an unmasked signal pending to complete
-pending operations.
-
-               /* KVM_EXIT_HYPERCALL */
-               struct {
-                       __u64 nr;
-                       __u64 args[6];
-                       __u64 ret;
-                       __u32 longmode;
-                       __u32 pad;
-               } hypercall;
-
-Unused.  This was once used for 'hypercall to userspace'.  To implement
-such functionality, use KVM_EXIT_IO (x86) or KVM_EXIT_MMIO (all except s390).
-Note KVM_EXIT_IO is significantly faster than KVM_EXIT_MMIO.
-
-               /* KVM_EXIT_TPR_ACCESS */
-               struct {
-                       __u64 rip;
-                       __u32 is_write;
-                       __u32 pad;
-               } tpr_access;
-
-To be documented (KVM_TPR_ACCESS_REPORTING).
-
-               /* KVM_EXIT_S390_SIEIC */
-               struct {
-                       __u8 icptcode;
-                       __u64 mask; /* psw upper half */
-                       __u64 addr; /* psw lower half */
-                       __u16 ipa;
-                       __u32 ipb;
-               } s390_sieic;
-
-s390 specific.
-
-               /* KVM_EXIT_S390_RESET */
-#define KVM_S390_RESET_POR       1
-#define KVM_S390_RESET_CLEAR     2
-#define KVM_S390_RESET_SUBSYSTEM 4
-#define KVM_S390_RESET_CPU_INIT  8
-#define KVM_S390_RESET_IPL       16
-               __u64 s390_reset_flags;
-
-s390 specific.
-
-               /* KVM_EXIT_S390_UCONTROL */
-               struct {
-                       __u64 trans_exc_code;
-                       __u32 pgm_code;
-               } s390_ucontrol;
-
-s390 specific. A page fault has occurred for a user controlled virtual
-machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
-resolved by the kernel.
-The program code and the translation exception code that were placed
-in the cpu's lowcore are presented here as defined by the z Architecture
-Principles of Operation Book in the Chapter for Dynamic Address Translation
-(DAT)
-
-               /* KVM_EXIT_DCR */
-               struct {
-                       __u32 dcrn;
-                       __u32 data;
-                       __u8  is_write;
-               } dcr;
-
-Deprecated - was used for 440 KVM.
-
-               /* KVM_EXIT_OSI */
-               struct {
-                       __u64 gprs[32];
-               } osi;
-
-MOL uses a special hypercall interface it calls 'OSI'. To enable it, we catch
-hypercalls and exit with this exit struct that contains all the guest gprs.
-
-If exit_reason is KVM_EXIT_OSI, then the vcpu has triggered such a hypercall.
-Userspace can now handle the hypercall and when it's done modify the gprs as
-necessary. Upon guest entry all guest GPRs will then be replaced by the values
-in this struct.
-
-               /* KVM_EXIT_PAPR_HCALL */
-               struct {
-                       __u64 nr;
-                       __u64 ret;
-                       __u64 args[9];
-               } papr_hcall;
-
-This is used on 64-bit PowerPC when emulating a pSeries partition,
-e.g. with the 'pseries' machine type in qemu.  It occurs when the
-guest does a hypercall using the 'sc 1' instruction.  The 'nr' field
-contains the hypercall number (from the guest R3), and 'args' contains
-the arguments (from the guest R4 - R12).  Userspace should put the
-return code in 'ret' and any extra returned values in args[].
-The possible hypercalls are defined in the Power Architecture Platform
-Requirements (PAPR) document available from www.power.org (free
-developer registration required to access it).
-
-               /* KVM_EXIT_S390_TSCH */
-               struct {
-                       __u16 subchannel_id;
-                       __u16 subchannel_nr;
-                       __u32 io_int_parm;
-                       __u32 io_int_word;
-                       __u32 ipb;
-                       __u8 dequeued;
-               } s390_tsch;
-
-s390 specific. This exit occurs when KVM_CAP_S390_CSS_SUPPORT has been enabled
-and TEST SUBCHANNEL was intercepted. If dequeued is set, a pending I/O
-interrupt for the target subchannel has been dequeued and subchannel_id,
-subchannel_nr, io_int_parm and io_int_word contain the parameters for that
-interrupt. ipb is needed for instruction parameter decoding.
-
-               /* KVM_EXIT_EPR */
-               struct {
-                       __u32 epr;
-               } epr;
-
-On FSL BookE PowerPC chips, the interrupt controller has a fast patch
-interrupt acknowledge path to the core. When the core successfully
-delivers an interrupt, it automatically populates the EPR register with
-the interrupt vector number and acknowledges the interrupt inside
-the interrupt controller.
-
-In case the interrupt controller lives in user space, we need to do
-the interrupt acknowledge cycle through it to fetch the next to be
-delivered interrupt vector using this exit.
-
-It gets triggered whenever both KVM_CAP_PPC_EPR are enabled and an
-external interrupt has just been delivered into the guest. User space
-should put the acknowledged interrupt vector into the 'epr' field.
-
-               /* KVM_EXIT_SYSTEM_EVENT */
-               struct {
-#define KVM_SYSTEM_EVENT_SHUTDOWN       1
-#define KVM_SYSTEM_EVENT_RESET          2
-#define KVM_SYSTEM_EVENT_CRASH          3
-                       __u32 type;
-                       __u64 flags;
-               } system_event;
-
-If exit_reason is KVM_EXIT_SYSTEM_EVENT then the vcpu has triggered
-a system-level event using some architecture specific mechanism (hypercall
-or some special instruction). In case of ARM/ARM64, this is triggered using
-HVC instruction based PSCI call from the vcpu. The 'type' field describes
-the system-level event type. The 'flags' field describes architecture
-specific flags for the system-level event.
-
-Valid values for 'type' are:
-  KVM_SYSTEM_EVENT_SHUTDOWN -- the guest has requested a shutdown of the
-   VM. Userspace is not obliged to honour this, and if it does honour
-   this does not need to destroy the VM synchronously (ie it may call
-   KVM_RUN again before shutdown finally occurs).
-  KVM_SYSTEM_EVENT_RESET -- the guest has requested a reset of the VM.
-   As with SHUTDOWN, userspace can choose to ignore the request, or
-   to schedule the reset to occur in the future and may call KVM_RUN again.
-  KVM_SYSTEM_EVENT_CRASH -- the guest crash occurred and the guest
-   has requested a crash condition maintenance. Userspace can choose
-   to ignore the request, or to gather VM memory core dump and/or
-   reset/shutdown of the VM.
-
-               /* KVM_EXIT_IOAPIC_EOI */
-               struct {
-                       __u8 vector;
-               } eoi;
-
-Indicates that the VCPU's in-kernel local APIC received an EOI for a
-level-triggered IOAPIC interrupt.  This exit only triggers when the
-IOAPIC is implemented in userspace (i.e. KVM_CAP_SPLIT_IRQCHIP is enabled);
-the userspace IOAPIC should process the EOI and retrigger the interrupt if
-it is still asserted.  Vector is the LAPIC interrupt vector for which the
-EOI was received.
-
-               struct kvm_hyperv_exit {
-#define KVM_EXIT_HYPERV_SYNIC          1
-#define KVM_EXIT_HYPERV_HCALL          2
-                       __u32 type;
-                       union {
-                               struct {
-                                       __u32 msr;
-                                       __u64 control;
-                                       __u64 evt_page;
-                                       __u64 msg_page;
-                               } synic;
-                               struct {
-                                       __u64 input;
-                                       __u64 result;
-                                       __u64 params[2];
-                               } hcall;
-                       } u;
-               };
-               /* KVM_EXIT_HYPERV */
-                struct kvm_hyperv_exit hyperv;
-Indicates that the VCPU exits into userspace to process some tasks
-related to Hyper-V emulation.
-Valid values for 'type' are:
-       KVM_EXIT_HYPERV_SYNIC -- synchronously notify user-space about
-Hyper-V SynIC state change. Notification is used to remap SynIC
-event/message pages and to enable/disable SynIC messages/events processing
-in userspace.
-
-               /* Fix the size of the union. */
-               char padding[256];
-       };
-
-       /*
-        * shared registers between kvm and userspace.
-        * kvm_valid_regs specifies the register classes set by the host
-        * kvm_dirty_regs specified the register classes dirtied by userspace
-        * struct kvm_sync_regs is architecture specific, as well as the
-        * bits for kvm_valid_regs and kvm_dirty_regs
-        */
-       __u64 kvm_valid_regs;
-       __u64 kvm_dirty_regs;
-       union {
-               struct kvm_sync_regs regs;
-               char padding[SYNC_REGS_SIZE_BYTES];
-       } s;
-
-If KVM_CAP_SYNC_REGS is defined, these fields allow userspace to access
-certain guest registers without having to call SET/GET_*REGS. Thus we can
-avoid some system call overhead if userspace has to handle the exit.
-Userspace can query the validity of the structure by checking
-kvm_valid_regs for specific bits. These bits are architecture specific
-and usually define the validity of a groups of registers. (e.g. one bit
- for general purpose registers)
-
-Please note that the kernel is allowed to use the kvm_run structure as the
-primary storage for certain register types. Therefore, the kernel may use the
-values in kvm_run even if the corresponding bit in kvm_dirty_regs is not set.
-
-};
-
-
-
-6. Capabilities that can be enabled on vCPUs
---------------------------------------------
-
-There are certain capabilities that change the behavior of the virtual CPU or
-the virtual machine when enabled. To enable them, please see section 4.37.
-Below you can find a list of capabilities and what their effect on the vCPU or
-the virtual machine is when enabling them.
-
-The following information is provided along with the description:
-
-  Architectures: which instruction set architectures provide this ioctl.
-      x86 includes both i386 and x86_64.
-
-  Target: whether this is a per-vcpu or per-vm capability.
-
-  Parameters: what parameters are accepted by the capability.
-
-  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
-      are not detailed, but errors with specific meanings are.
-
-
-6.1 KVM_CAP_PPC_OSI
-
-Architectures: ppc
-Target: vcpu
-Parameters: none
-Returns: 0 on success; -1 on error
-
-This capability enables interception of OSI hypercalls that otherwise would
-be treated as normal system calls to be injected into the guest. OSI hypercalls
-were invented by Mac-on-Linux to have a standardized communication mechanism
-between the guest and the host.
-
-When this capability is enabled, KVM_EXIT_OSI can occur.
-
-
-6.2 KVM_CAP_PPC_PAPR
-
-Architectures: ppc
-Target: vcpu
-Parameters: none
-Returns: 0 on success; -1 on error
-
-This capability enables interception of PAPR hypercalls. PAPR hypercalls are
-done using the hypercall instruction "sc 1".
-
-It also sets the guest privilege level to "supervisor" mode. Usually the guest
-runs in "hypervisor" privilege mode with a few missing features.
-
-In addition to the above, it changes the semantics of SDR1. In this mode, the
-HTAB address part of SDR1 contains an HVA instead of a GPA, as PAPR keeps the
-HTAB invisible to the guest.
-
-When this capability is enabled, KVM_EXIT_PAPR_HCALL can occur.
-
-
-6.3 KVM_CAP_SW_TLB
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] is the address of a struct kvm_config_tlb
-Returns: 0 on success; -1 on error
-
-struct kvm_config_tlb {
-       __u64 params;
-       __u64 array;
-       __u32 mmu_type;
-       __u32 array_len;
-};
-
-Configures the virtual CPU's TLB array, establishing a shared memory area
-between userspace and KVM.  The "params" and "array" fields are userspace
-addresses of mmu-type-specific data structures.  The "array_len" field is an
-safety mechanism, and should be set to the size in bytes of the memory that
-userspace has reserved for the array.  It must be at least the size dictated
-by "mmu_type" and "params".
-
-While KVM_RUN is active, the shared region is under control of KVM.  Its
-contents are undefined, and any modification by userspace results in
-boundedly undefined behavior.
-
-On return from KVM_RUN, the shared region will reflect the current state of
-the guest's TLB.  If userspace makes any changes, it must call KVM_DIRTY_TLB
-to tell KVM which entries have been changed, prior to calling KVM_RUN again
-on this vcpu.
-
-For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
- - The "params" field is of type "struct kvm_book3e_206_tlb_params".
- - The "array" field points to an array of type "struct
-   kvm_book3e_206_tlb_entry".
- - The array consists of all entries in the first TLB, followed by all
-   entries in the second TLB.
- - Within a TLB, entries are ordered first by increasing set number.  Within a
-   set, entries are ordered by way (increasing ESEL).
- - The hash for determining set number in TLB0 is: (MAS2 >> 12) & (num_sets - 1)
-   where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
- - The tsize field of mas1 shall be set to 4K on TLB0, even though the
-   hardware ignores this value for TLB0.
-
-6.4 KVM_CAP_S390_CSS_SUPPORT
-
-Architectures: s390
-Target: vcpu
-Parameters: none
-Returns: 0 on success; -1 on error
-
-This capability enables support for handling of channel I/O instructions.
-
-TEST PENDING INTERRUPTION and the interrupt portion of TEST SUBCHANNEL are
-handled in-kernel, while the other I/O instructions are passed to userspace.
-
-When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
-SUBCHANNEL intercepts.
-
-Note that even though this capability is enabled per-vcpu, the complete
-virtual machine is affected.
-
-6.5 KVM_CAP_PPC_EPR
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] defines whether the proxy facility is active
-Returns: 0 on success; -1 on error
-
-This capability enables or disables the delivery of interrupts through the
-external proxy facility.
-
-When enabled (args[0] != 0), every time the guest gets an external interrupt
-delivered, it automatically exits into user space with a KVM_EXIT_EPR exit
-to receive the topmost interrupt vector.
-
-When disabled (args[0] == 0), behavior is as if this facility is unsupported.
-
-When this capability is enabled, KVM_EXIT_EPR can occur.
-
-6.6 KVM_CAP_IRQ_MPIC
-
-Architectures: ppc
-Parameters: args[0] is the MPIC device fd
-            args[1] is the MPIC CPU number for this vcpu
-
-This capability connects the vcpu to an in-kernel MPIC device.
-
-6.7 KVM_CAP_IRQ_XICS
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] is the XICS device fd
-            args[1] is the XICS CPU number (server ID) for this vcpu
-
-This capability connects the vcpu to an in-kernel XICS device.
-
-6.8 KVM_CAP_S390_IRQCHIP
-
-Architectures: s390
-Target: vm
-Parameters: none
-
-This capability enables the in-kernel irqchip for s390. Please refer to
-"4.24 KVM_CREATE_IRQCHIP" for details.
-
-6.9 KVM_CAP_MIPS_FPU
-
-Architectures: mips
-Target: vcpu
-Parameters: args[0] is reserved for future use (should be 0).
-
-This capability allows the use of the host Floating Point Unit by the guest. It
-allows the Config1.FP bit to be set to enable the FPU in the guest. Once this is
-done the KVM_REG_MIPS_FPR_* and KVM_REG_MIPS_FCR_* registers can be accessed
-(depending on the current guest FPU register mode), and the Status.FR,
-Config5.FRE bits are accessible via the KVM API and also from the guest,
-depending on them being supported by the FPU.
-
-6.10 KVM_CAP_MIPS_MSA
-
-Architectures: mips
-Target: vcpu
-Parameters: args[0] is reserved for future use (should be 0).
-
-This capability allows the use of the MIPS SIMD Architecture (MSA) by the guest.
-It allows the Config3.MSAP bit to be set to enable the use of MSA by the guest.
-Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
-accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
-the guest.
-
-6.74 KVM_CAP_SYNC_REGS
-Architectures: s390, x86
-Target: s390: always enabled, x86: vcpu
-Parameters: none
-Returns: x86: KVM_CHECK_EXTENSION returns a bit-array indicating which register
-sets are supported (bitfields defined in arch/x86/include/uapi/asm/kvm.h).
-
-As described above in the kvm_sync_regs struct info in section 5 (kvm_run):
-KVM_CAP_SYNC_REGS "allow[s] userspace to access certain guest registers
-without having to call SET/GET_*REGS". This reduces overhead by eliminating
-repeated ioctl calls for setting and/or getting register values. This is
-particularly important when userspace is making synchronous guest state
-modifications, e.g. when emulating and/or intercepting instructions in
-userspace.
-
-For s390 specifics, please refer to the source code.
-
-For x86:
-- the register sets to be copied out to kvm_run are selectable
-  by userspace (rather that all sets being copied out for every exit).
-- vcpu_events are available in addition to regs and sregs.
-
-For x86, the 'kvm_valid_regs' field of struct kvm_run is overloaded to
-function as an input bit-array field set by userspace to indicate the
-specific register sets to be copied out on the next exit.
-
-To indicate when userspace has modified values that should be copied into
-the vCPU, the all architecture bitarray field, 'kvm_dirty_regs' must be set.
-This is done using the same bitflags as for the 'kvm_valid_regs' field.
-If the dirty bit is not set, then the register set values will not be copied
-into the vCPU even if they've been modified.
-
-Unused bitfields in the bitarrays must be set to zero.
-
-struct kvm_sync_regs {
-        struct kvm_regs regs;
-        struct kvm_sregs sregs;
-        struct kvm_vcpu_events events;
-};
-
-6.75 KVM_CAP_PPC_IRQ_XIVE
-
-Architectures: ppc
-Target: vcpu
-Parameters: args[0] is the XIVE device fd
-            args[1] is the XIVE CPU number (server ID) for this vcpu
-
-This capability connects the vcpu to an in-kernel XIVE device.
-
-7. Capabilities that can be enabled on VMs
-------------------------------------------
-
-There are certain capabilities that change the behavior of the virtual
-machine when enabled. To enable them, please see section 4.37. Below
-you can find a list of capabilities and what their effect on the VM
-is when enabling them.
-
-The following information is provided along with the description:
-
-  Architectures: which instruction set architectures provide this ioctl.
-      x86 includes both i386 and x86_64.
-
-  Parameters: what parameters are accepted by the capability.
-
-  Returns: the return value.  General error numbers (EBADF, ENOMEM, EINVAL)
-      are not detailed, but errors with specific meanings are.
-
-
-7.1 KVM_CAP_PPC_ENABLE_HCALL
-
-Architectures: ppc
-Parameters: args[0] is the sPAPR hcall number
-           args[1] is 0 to disable, 1 to enable in-kernel handling
-
-This capability controls whether individual sPAPR hypercalls (hcalls)
-get handled by the kernel or not.  Enabling or disabling in-kernel
-handling of an hcall is effective across the VM.  On creation, an
-initial set of hcalls are enabled for in-kernel handling, which
-consists of those hcalls for which in-kernel handlers were implemented
-before this capability was implemented.  If disabled, the kernel will
-not to attempt to handle the hcall, but will always exit to userspace
-to handle it.  Note that it may not make sense to enable some and
-disable others of a group of related hcalls, but KVM does not prevent
-userspace from doing that.
-
-If the hcall number specified is not one that has an in-kernel
-implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL
-error.
-
-7.2 KVM_CAP_S390_USER_SIGP
-
-Architectures: s390
-Parameters: none
-
-This capability controls which SIGP orders will be handled completely in user
-space. With this capability enabled, all fast orders will be handled completely
-in the kernel:
-- SENSE
-- SENSE RUNNING
-- EXTERNAL CALL
-- EMERGENCY SIGNAL
-- CONDITIONAL EMERGENCY SIGNAL
-
-All other orders will be handled completely in user space.
-
-Only privileged operation exceptions will be checked for in the kernel (or even
-in the hardware prior to interception). If this capability is not enabled, the
-old way of handling SIGP orders is used (partially in kernel and user space).
-
-7.3 KVM_CAP_S390_VECTOR_REGISTERS
-
-Architectures: s390
-Parameters: none
-Returns: 0 on success, negative value on error
-
-Allows use of the vector registers introduced with z13 processor, and
-provides for the synchronization between host and user space.  Will
-return -EINVAL if the machine does not support vectors.
-
-7.4 KVM_CAP_S390_USER_STSI
-
-Architectures: s390
-Parameters: none
-
-This capability allows post-handlers for the STSI instruction. After
-initial handling in the kernel, KVM exits to user space with
-KVM_EXIT_S390_STSI to allow user space to insert further data.
-
-Before exiting to userspace, kvm handlers should fill in s390_stsi field of
-vcpu->run:
-struct {
-       __u64 addr;
-       __u8 ar;
-       __u8 reserved;
-       __u8 fc;
-       __u8 sel1;
-       __u16 sel2;
-} s390_stsi;
-
-@addr - guest address of STSI SYSIB
-@fc   - function code
-@sel1 - selector 1
-@sel2 - selector 2
-@ar   - access register number
-
-KVM handlers should exit to userspace with rc = -EREMOTE.
-
-7.5 KVM_CAP_SPLIT_IRQCHIP
-
-Architectures: x86
-Parameters: args[0] - number of routes reserved for userspace IOAPICs
-Returns: 0 on success, -1 on error
-
-Create a local apic for each processor in the kernel. This can be used
-instead of KVM_CREATE_IRQCHIP if the userspace VMM wishes to emulate the
-IOAPIC and PIC (and also the PIT, even though this has to be enabled
-separately).
-
-This capability also enables in kernel routing of interrupt requests;
-when KVM_CAP_SPLIT_IRQCHIP only routes of KVM_IRQ_ROUTING_MSI type are
-used in the IRQ routing table.  The first args[0] MSI routes are reserved
-for the IOAPIC pins.  Whenever the LAPIC receives an EOI for these routes,
-a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace.
-
-Fails if VCPU has already been created, or if the irqchip is already in the
-kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
-
-7.6 KVM_CAP_S390_RI
-
-Architectures: s390
-Parameters: none
-
-Allows use of runtime-instrumentation introduced with zEC12 processor.
-Will return -EINVAL if the machine does not support runtime-instrumentation.
-Will return -EBUSY if a VCPU has already been created.
-
-7.7 KVM_CAP_X2APIC_API
-
-Architectures: x86
-Parameters: args[0] - features that should be enabled
-Returns: 0 on success, -EINVAL when args[0] contains invalid features
-
-Valid feature flags in args[0] are
-
-#define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
-#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
-
-Enabling KVM_X2APIC_API_USE_32BIT_IDS changes the behavior of
-KVM_SET_GSI_ROUTING, KVM_SIGNAL_MSI, KVM_SET_LAPIC, and KVM_GET_LAPIC,
-allowing the use of 32-bit APIC IDs.  See KVM_CAP_X2APIC_API in their
-respective sections.
-
-KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK must be enabled for x2APIC to work
-in logical mode or with more than 255 VCPUs.  Otherwise, KVM treats 0xff
-as a broadcast even in x2APIC mode in order to support physical x2APIC
-without interrupt remapping.  This is undesirable in logical mode,
-where 0xff represents CPUs 0-7 in cluster 0.
-
-7.8 KVM_CAP_S390_USER_INSTR0
-
-Architectures: s390
-Parameters: none
-
-With this capability enabled, all illegal instructions 0x0000 (2 bytes) will
-be intercepted and forwarded to user space. User space can use this
-mechanism e.g. to realize 2-byte software breakpoints. The kernel will
-not inject an operating exception for these instructions, user space has
-to take care of that.
-
-This capability can be enabled dynamically even if VCPUs were already
-created and are running.
-
-7.9 KVM_CAP_S390_GS
-
-Architectures: s390
-Parameters: none
-Returns: 0 on success; -EINVAL if the machine does not support
-        guarded storage; -EBUSY if a VCPU has already been created.
-
-Allows use of guarded storage for the KVM guest.
-
-7.10 KVM_CAP_S390_AIS
-
-Architectures: s390
-Parameters: none
-
-Allow use of adapter-interruption suppression.
-Returns: 0 on success; -EBUSY if a VCPU has already been created.
-
-7.11 KVM_CAP_PPC_SMT
-
-Architectures: ppc
-Parameters: vsmt_mode, flags
-
-Enabling this capability on a VM provides userspace with a way to set
-the desired virtual SMT mode (i.e. the number of virtual CPUs per
-virtual core).  The virtual SMT mode, vsmt_mode, must be a power of 2
-between 1 and 8.  On POWER8, vsmt_mode must also be no greater than
-the number of threads per subcore for the host.  Currently flags must
-be 0.  A successful call to enable this capability will result in
-vsmt_mode being returned when the KVM_CAP_PPC_SMT capability is
-subsequently queried for the VM.  This capability is only supported by
-HV KVM, and can only be set before any VCPUs have been created.
-The KVM_CAP_PPC_SMT_POSSIBLE capability indicates which virtual SMT
-modes are available.
-
-7.12 KVM_CAP_PPC_FWNMI
-
-Architectures: ppc
-Parameters: none
-
-With this capability a machine check exception in the guest address
-space will cause KVM to exit the guest with NMI exit reason. This
-enables QEMU to build error log and branch to guest kernel registered
-machine check handling routine. Without this capability KVM will
-branch to guests' 0x200 interrupt vector.
-
-7.13 KVM_CAP_X86_DISABLE_EXITS
-
-Architectures: x86
-Parameters: args[0] defines which exits are disabled
-Returns: 0 on success, -EINVAL when args[0] contains invalid exits
-
-Valid bits in args[0] are
-
-#define KVM_X86_DISABLE_EXITS_MWAIT            (1 << 0)
-#define KVM_X86_DISABLE_EXITS_HLT              (1 << 1)
-#define KVM_X86_DISABLE_EXITS_PAUSE            (1 << 2)
-#define KVM_X86_DISABLE_EXITS_CSTATE           (1 << 3)
-
-Enabling this capability on a VM provides userspace with a way to no
-longer intercept some instructions for improved latency in some
-workloads, and is suggested when vCPUs are associated to dedicated
-physical CPUs.  More bits can be added in the future; userspace can
-just pass the KVM_CHECK_EXTENSION result to KVM_ENABLE_CAP to disable
-all such vmexits.
-
-Do not enable KVM_FEATURE_PV_UNHALT if you disable HLT exits.
-
-7.14 KVM_CAP_S390_HPAGE_1M
-
-Architectures: s390
-Parameters: none
-Returns: 0 on success, -EINVAL if hpage module parameter was not set
-        or cmma is enabled, or the VM has the KVM_VM_S390_UCONTROL
-        flag set
-
-With this capability the KVM support for memory backing with 1m pages
-through hugetlbfs can be enabled for a VM. After the capability is
-enabled, cmma can't be enabled anymore and pfmfi and the storage key
-interpretation are disabled. If cmma has already been enabled or the
-hpage module parameter is not set to 1, -EINVAL is returned.
-
-While it is generally possible to create a huge page backed VM without
-this capability, the VM will not be able to run.
-
-7.15 KVM_CAP_MSR_PLATFORM_INFO
-
-Architectures: x86
-Parameters: args[0] whether feature should be enabled or not
-
-With this capability, a guest may read the MSR_PLATFORM_INFO MSR. Otherwise,
-a #GP would be raised when the guest tries to access. Currently, this
-capability does not enable write permissions of this MSR for the guest.
-
-7.16 KVM_CAP_PPC_NESTED_HV
-
-Architectures: ppc
-Parameters: none
-Returns: 0 on success, -EINVAL when the implementation doesn't support
-        nested-HV virtualization.
-
-HV-KVM on POWER9 and later systems allows for "nested-HV"
-virtualization, which provides a way for a guest VM to run guests that
-can run using the CPU's supervisor mode (privileged non-hypervisor
-state).  Enabling this capability on a VM depends on the CPU having
-the necessary functionality and on the facility being enabled with a
-kvm-hv module parameter.
-
-7.17 KVM_CAP_EXCEPTION_PAYLOAD
-
-Architectures: x86
-Parameters: args[0] whether feature should be enabled or not
-
-With this capability enabled, CR2 will not be modified prior to the
-emulated VM-exit when L1 intercepts a #PF exception that occurs in
-L2. Similarly, for kvm-intel only, DR6 will not be modified prior to
-the emulated VM-exit when L1 intercepts a #DB exception that occurs in
-L2. As a result, when KVM_GET_VCPU_EVENTS reports a pending #PF (or
-#DB) exception for L2, exception.has_payload will be set and the
-faulting address (or the new DR6 bits*) will be reported in the
-exception_payload field. Similarly, when userspace injects a #PF (or
-#DB) into L2 using KVM_SET_VCPU_EVENTS, it is expected to set
-exception.has_payload and to put the faulting address (or the new DR6
-bits*) in the exception_payload field.
-
-This capability also enables exception.pending in struct
-kvm_vcpu_events, which allows userspace to distinguish between pending
-and injected exceptions.
-
-
-* For the new DR6 bits, note that bit 16 is set iff the #DB exception
-  will clear DR6.RTM.
-
-7.18 KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2
-
-Architectures: x86, arm, arm64, mips
-Parameters: args[0] whether feature should be enabled or not
-
-With this capability enabled, KVM_GET_DIRTY_LOG will not automatically
-clear and write-protect all pages that are returned as dirty.
-Rather, userspace will have to do this operation separately using
-KVM_CLEAR_DIRTY_LOG.
-
-At the cost of a slightly more complicated operation, this provides better
-scalability and responsiveness for two reasons.  First,
-KVM_CLEAR_DIRTY_LOG ioctl can operate on a 64-page granularity rather
-than requiring to sync a full memslot; this ensures that KVM does not
-take spinlocks for an extended period of time.  Second, in some cases a
-large amount of time can pass between a call to KVM_GET_DIRTY_LOG and
-userspace actually using the data in the page.  Pages can be modified
-during this time, which is inefficint for both the guest and userspace:
-the guest will incur a higher penalty due to write protection faults,
-while userspace can see false reports of dirty pages.  Manual reprotection
-helps reducing this time, improving guest performance and reducing the
-number of dirty log false positives.
-
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make
-it hard or impossible to use it correctly.  The availability of
-KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 signals that those bugs are fixed.
-Userspace should not try to use KVM_CAP_MANUAL_DIRTY_LOG_PROTECT.
-
-8. Other capabilities.
-----------------------
-
-This section lists capabilities that give information about other
-features of the KVM implementation.
-
-8.1 KVM_CAP_PPC_HWRNG
-
-Architectures: ppc
-
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel has an implementation of the
-H_RANDOM hypercall backed by a hardware random-number generator.
-If present, the kernel H_RANDOM handler can be enabled for guest use
-with the KVM_CAP_PPC_ENABLE_HCALL capability.
-
-8.2 KVM_CAP_HYPERV_SYNIC
-
-Architectures: x86
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel has an implementation of the
-Hyper-V Synthetic interrupt controller(SynIC). Hyper-V SynIC is
-used to support Windows Hyper-V based guest paravirt drivers(VMBus).
-
-In order to use SynIC, it has to be activated by setting this
-capability via KVM_ENABLE_CAP ioctl on the vcpu fd. Note that this
-will disable the use of APIC hardware virtualization even if supported
-by the CPU, as it's incompatible with SynIC auto-EOI behavior.
-
-8.3 KVM_CAP_PPC_RADIX_MMU
-
-Architectures: ppc
-
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel can support guests using the
-radix MMU defined in Power ISA V3.00 (as implemented in the POWER9
-processor).
-
-8.4 KVM_CAP_PPC_HASH_MMU_V3
-
-Architectures: ppc
-
-This capability, if KVM_CHECK_EXTENSION indicates that it is
-available, means that that the kernel can support guests using the
-hashed page table MMU defined in Power ISA V3.00 (as implemented in
-the POWER9 processor), including in-memory segment tables.
-
-8.5 KVM_CAP_MIPS_VZ
-
-Architectures: mips
-
-This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
-it is available, means that full hardware assisted virtualization capabilities
-of the hardware are available for use through KVM. An appropriate
-KVM_VM_MIPS_* type must be passed to KVM_CREATE_VM to create a VM which
-utilises it.
-
-If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
-available, it means that the VM is using full hardware assisted virtualization
-capabilities of the hardware. This is useful to check after creating a VM with
-KVM_VM_MIPS_DEFAULT.
-
-The value returned by KVM_CHECK_EXTENSION should be compared against known
-values (see below). All other values are reserved. This is to allow for the
-possibility of other hardware assisted virtualization implementations which
-may be incompatible with the MIPS VZ ASE.
-
- 0: The trap & emulate implementation is in use to run guest code in user
-    mode. Guest virtual memory segments are rearranged to fit the guest in the
-    user mode address space.
-
- 1: The MIPS VZ ASE is in use, providing full hardware assisted
-    virtualization, including standard guest virtual memory segments.
-
-8.6 KVM_CAP_MIPS_TE
-
-Architectures: mips
-
-This capability, if KVM_CHECK_EXTENSION on the main kvm handle indicates that
-it is available, means that the trap & emulate implementation is available to
-run guest code in user mode, even if KVM_CAP_MIPS_VZ indicates that hardware
-assisted virtualisation is also available. KVM_VM_MIPS_TE (0) must be passed
-to KVM_CREATE_VM to create a VM which utilises it.
-
-If KVM_CHECK_EXTENSION on a kvm VM handle indicates that this capability is
-available, it means that the VM is using trap & emulate.
-
-8.7 KVM_CAP_MIPS_64BIT
-
-Architectures: mips
-
-This capability indicates the supported architecture type of the guest, i.e. the
-supported register and address width.
-
-The values returned when this capability is checked by KVM_CHECK_EXTENSION on a
-kvm VM handle correspond roughly to the CP0_Config.AT register field, and should
-be checked specifically against known values (see below). All other values are
-reserved.
-
- 0: MIPS32 or microMIPS32.
-    Both registers and addresses are 32-bits wide.
-    It will only be possible to run 32-bit guest code.
-
- 1: MIPS64 or microMIPS64 with access only to 32-bit compatibility segments.
-    Registers are 64-bits wide, but addresses are 32-bits wide.
-    64-bit guest code may run but cannot access MIPS64 memory segments.
-    It will also be possible to run 32-bit guest code.
-
- 2: MIPS64 or microMIPS64 with access to all address segments.
-    Both registers and addresses are 64-bits wide.
-    It will be possible to run 64-bit or 32-bit guest code.
-
-8.9 KVM_CAP_ARM_USER_IRQ
-
-Architectures: arm, arm64
-This capability, if KVM_CHECK_EXTENSION indicates that it is available, means
-that if userspace creates a VM without an in-kernel interrupt controller, it
-will be notified of changes to the output level of in-kernel emulated devices,
-which can generate virtual interrupts, presented to the VM.
-For such VMs, on every return to userspace, the kernel
-updates the vcpu's run->s.regs.device_irq_level field to represent the actual
-output level of the device.
-
-Whenever kvm detects a change in the device output level, kvm guarantees at
-least one return to userspace before running the VM.  This exit could either
-be a KVM_EXIT_INTR or any other exit event, like KVM_EXIT_MMIO. This way,
-userspace can always sample the device output level and re-compute the state of
-the userspace interrupt controller.  Userspace should always check the state
-of run->s.regs.device_irq_level on every kvm exit.
-The value in run->s.regs.device_irq_level can represent both level and edge
-triggered interrupt signals, depending on the device.  Edge triggered interrupt
-signals will exit to userspace with the bit in run->s.regs.device_irq_level
-set exactly once per edge signal.
-
-The field run->s.regs.device_irq_level is available independent of
-run->kvm_valid_regs or run->kvm_dirty_regs bits.
-
-If KVM_CAP_ARM_USER_IRQ is supported, the KVM_CHECK_EXTENSION ioctl returns a
-number larger than 0 indicating the version of this capability is implemented
-and thereby which bits in in run->s.regs.device_irq_level can signal values.
-
-Currently the following bits are defined for the device_irq_level bitmap:
-
-  KVM_CAP_ARM_USER_IRQ >= 1:
-
-    KVM_ARM_DEV_EL1_VTIMER -  EL1 virtual timer
-    KVM_ARM_DEV_EL1_PTIMER -  EL1 physical timer
-    KVM_ARM_DEV_PMU        -  ARM PMU overflow interrupt signal
-
-Future versions of kvm may implement additional events. These will get
-indicated by returning a higher number from KVM_CHECK_EXTENSION and will be
-listed above.
-
-8.10 KVM_CAP_PPC_SMT_POSSIBLE
-
-Architectures: ppc
-
-Querying this capability returns a bitmap indicating the possible
-virtual SMT modes that can be set using KVM_CAP_PPC_SMT.  If bit N
-(counting from the right) is set, then a virtual SMT mode of 2^N is
-available.
-
-8.11 KVM_CAP_HYPERV_SYNIC2
-
-Architectures: x86
-
-This capability enables a newer version of Hyper-V Synthetic interrupt
-controller (SynIC).  The only difference with KVM_CAP_HYPERV_SYNIC is that KVM
-doesn't clear SynIC message and event flags pages when they are enabled by
-writing to the respective MSRs.
-
-8.12 KVM_CAP_HYPERV_VP_INDEX
-
-Architectures: x86
-
-This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr.  Its
-value is used to denote the target vcpu for a SynIC interrupt.  For
-compatibilty, KVM initializes this msr to KVM's internal vcpu index.  When this
-capability is absent, userspace can still query this msr's value.
-
-8.13 KVM_CAP_S390_AIS_MIGRATION
-
-Architectures: s390
-Parameters: none
-
-This capability indicates if the flic device will be able to get/set the
-AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows
-to discover this without having to create a flic device.
-
-8.14 KVM_CAP_S390_PSW
-
-Architectures: s390
-
-This capability indicates that the PSW is exposed via the kvm_run structure.
-
-8.15 KVM_CAP_S390_GMAP
-
-Architectures: s390
-
-This capability indicates that the user space memory used as guest mapping can
-be anywhere in the user memory address space, as long as the memory slots are
-aligned and sized to a segment (1MB) boundary.
-
-8.16 KVM_CAP_S390_COW
-
-Architectures: s390
-
-This capability indicates that the user space memory used as guest mapping can
-use copy-on-write semantics as well as dirty pages tracking via read-only page
-tables.
-
-8.17 KVM_CAP_S390_BPB
-
-Architectures: s390
-
-This capability indicates that kvm will implement the interfaces to handle
-reset, migration and nested KVM for branch prediction blocking. The stfle
-facility 82 should not be provided to the guest without this capability.
-
-8.18 KVM_CAP_HYPERV_TLBFLUSH
-
-Architectures: x86
-
-This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush
-hypercalls:
-HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx,
-HvFlushVirtualAddressList, HvFlushVirtualAddressListEx.
-
-8.19 KVM_CAP_ARM_INJECT_SERROR_ESR
-
-Architectures: arm, arm64
-
-This capability indicates that userspace can specify (via the
-KVM_SET_VCPU_EVENTS ioctl) the syndrome value reported to the guest when it
-takes a virtual SError interrupt exception.
-If KVM advertises this capability, userspace can only specify the ISS field for
-the ESR syndrome. Other parts of the ESR, such as the EC are generated by the
-CPU when the exception is taken. If this virtual SError is taken to EL1 using
-AArch64, this value will be reported in the ISS field of ESR_ELx.
-
-See KVM_CAP_VCPU_EVENTS for more details.
-8.20 KVM_CAP_HYPERV_SEND_IPI
-
-Architectures: x86
-
-This capability indicates that KVM supports paravirtualized Hyper-V IPI send
-hypercalls:
-HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx.
diff --git a/Documentation/virtual/kvm/arm/hyp-abi.txt b/Documentation/virtual/kvm/arm/hyp-abi.txt
deleted file mode 100644 (file)
index a20a0be..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-* Internal ABI between the kernel and HYP
-
-This file documents the interaction between the Linux kernel and the
-hypervisor layer when running Linux as a hypervisor (for example
-KVM). It doesn't cover the interaction of the kernel with the
-hypervisor when running as a guest (under Xen, KVM or any other
-hypervisor), or any hypervisor-specific interaction when the kernel is
-used as a host.
-
-On arm and arm64 (without VHE), the kernel doesn't run in hypervisor
-mode, but still needs to interact with it, allowing a built-in
-hypervisor to be either installed or torn down.
-
-In order to achieve this, the kernel must be booted at HYP (arm) or
-EL2 (arm64), allowing it to install a set of stubs before dropping to
-SVC/EL1. These stubs are accessible by using a 'hvc #0' instruction,
-and only act on individual CPUs.
-
-Unless specified otherwise, any built-in hypervisor must implement
-these functions (see arch/arm{,64}/include/asm/virt.h):
-
-* r0/x0 = HVC_SET_VECTORS
-  r1/x1 = vectors
-
-  Set HVBAR/VBAR_EL2 to 'vectors' to enable a hypervisor. 'vectors'
-  must be a physical address, and respect the alignment requirements
-  of the architecture. Only implemented by the initial stubs, not by
-  Linux hypervisors.
-
-* r0/x0 = HVC_RESET_VECTORS
-
-  Turn HYP/EL2 MMU off, and reset HVBAR/VBAR_EL2 to the initials
-  stubs' exception vector value. This effectively disables an existing
-  hypervisor.
-
-* r0/x0 = HVC_SOFT_RESTART
-  r1/x1 = restart address
-  x2 = x0's value when entering the next payload (arm64)
-  x3 = x1's value when entering the next payload (arm64)
-  x4 = x2's value when entering the next payload (arm64)
-
-  Mask all exceptions, disable the MMU, move the arguments into place
-  (arm64 only), and jump to the restart address while at HYP/EL2. This
-  hypercall is not expected to return to its caller.
-
-Any other value of r0/x0 triggers a hypervisor-specific handling,
-which is not documented here.
-
-The return value of a stub hypercall is held by r0/x0, and is 0 on
-success, and HVC_STUB_ERR on error. A stub hypercall is allowed to
-clobber any of the caller-saved registers (x0-x18 on arm64, r0-r3 and
-ip on arm). It is thus recommended to use a function call to perform
-the hypercall.
diff --git a/Documentation/virtual/kvm/arm/psci.txt b/Documentation/virtual/kvm/arm/psci.txt
deleted file mode 100644 (file)
index 559586f..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-KVM implements the PSCI (Power State Coordination Interface)
-specification in order to provide services such as CPU on/off, reset
-and power-off to the guest.
-
-The PSCI specification is regularly updated to provide new features,
-and KVM implements these updates if they make sense from a virtualization
-point of view.
-
-This means that a guest booted on two different versions of KVM can
-observe two different "firmware" revisions. This could cause issues if
-a given guest is tied to a particular PSCI revision (unlikely), or if
-a migration causes a different PSCI version to be exposed out of the
-blue to an unsuspecting guest.
-
-In order to remedy this situation, KVM exposes a set of "firmware
-pseudo-registers" that can be manipulated using the GET/SET_ONE_REG
-interface. These registers can be saved/restored by userspace, and set
-to a convenient value if required.
-
-The following register is defined:
-
-* KVM_REG_ARM_PSCI_VERSION:
-
-  - Only valid if the vcpu has the KVM_ARM_VCPU_PSCI_0_2 feature set
-    (and thus has already been initialized)
-  - Returns the current PSCI version on GET_ONE_REG (defaulting to the
-    highest PSCI version implemented by KVM and compatible with v0.2)
-  - Allows any PSCI version implemented by KVM and compatible with
-    v0.2 to be set with SET_ONE_REG
-  - Affects the whole VM (even if the register view is per-vcpu)
-
-* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
-  Holds the state of the firmware support to mitigate CVE-2017-5715, as
-  offered by KVM to the guest via a HVC call. The workaround is described
-  under SMCCC_ARCH_WORKAROUND_1 in [1].
-  Accepted values are:
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL: KVM does not offer
-      firmware support for the workaround. The mitigation status for the
-      guest is unknown.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL: The workaround HVC call is
-      available to the guest and required for the mitigation.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED: The workaround HVC call
-      is available to the guest, but it is not needed on this VCPU.
-
-* KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
-  Holds the state of the firmware support to mitigate CVE-2018-3639, as
-  offered by KVM to the guest via a HVC call. The workaround is described
-  under SMCCC_ARCH_WORKAROUND_2 in [1].
-  Accepted values are:
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL: A workaround is not
-      available. KVM does not offer firmware support for the workaround.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN: The workaround state is
-      unknown. KVM does not offer firmware support for the workaround.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL: The workaround is available,
-      and can be disabled by a vCPU. If
-      KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED is set, it is active for
-      this vCPU.
-    KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED: The workaround is
-      always active on this vCPU or it is not needed.
-
-[1] https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf
diff --git a/Documentation/virtual/kvm/cpuid.rst b/Documentation/virtual/kvm/cpuid.rst
deleted file mode 100644 (file)
index 01b081f..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==============
-KVM CPUID bits
-==============
-
-:Author: Glauber Costa <glommer@gmail.com>
-
-A guest running on a kvm host, can check some of its features using
-cpuid. This is not always guaranteed to work, since userspace can
-mask-out some, or even all KVM-related cpuid features before launching
-a guest.
-
-KVM cpuid functions are:
-
-function: KVM_CPUID_SIGNATURE (0x40000000)
-
-returns::
-
-   eax = 0x40000001
-   ebx = 0x4b4d564b
-   ecx = 0x564b4d56
-   edx = 0x4d
-
-Note that this value in ebx, ecx and edx corresponds to the string "KVMKVMKVM".
-The value in eax corresponds to the maximum cpuid function present in this leaf,
-and will be updated if more functions are added in the future.
-Note also that old hosts set eax value to 0x0. This should
-be interpreted as if the value was 0x40000001.
-This function queries the presence of KVM cpuid leafs.
-
-function: define KVM_CPUID_FEATURES (0x40000001)
-
-returns::
-
-          ebx, ecx
-          eax = an OR'ed group of (1 << flag)
-
-where ``flag`` is defined as below:
-
-================================= =========== ================================
-flag                              value       meaning
-================================= =========== ================================
-KVM_FEATURE_CLOCKSOURCE           0           kvmclock available at msrs
-                                              0x11 and 0x12
-
-KVM_FEATURE_NOP_IO_DELAY          1           not necessary to perform delays
-                                              on PIO operations
-
-KVM_FEATURE_MMU_OP                2           deprecated
-
-KVM_FEATURE_CLOCKSOURCE2          3           kvmclock available at msrs
-
-                                              0x4b564d00 and 0x4b564d01
-KVM_FEATURE_ASYNC_PF              4           async pf can be enabled by
-                                              writing to msr 0x4b564d02
-
-KVM_FEATURE_STEAL_TIME            5           steal time can be enabled by
-                                              writing to msr 0x4b564d03
-
-KVM_FEATURE_PV_EOI                6           paravirtualized end of interrupt
-                                              handler can be enabled by
-                                              writing to msr 0x4b564d04
-
-KVM_FEATURE_PV_UNHAULT            7           guest checks this feature bit
-                                              before enabling paravirtualized
-                                              spinlock support
-
-KVM_FEATURE_PV_TLB_FLUSH          9           guest checks this feature bit
-                                              before enabling paravirtualized
-                                              tlb flush
-
-KVM_FEATURE_ASYNC_PF_VMEXIT       10          paravirtualized async PF VM EXIT
-                                              can be enabled by setting bit 2
-                                              when writing to msr 0x4b564d02
-
-KVM_FEATURE_PV_SEND_IPI           11          guest checks this feature bit
-                                              before enabling paravirtualized
-                                              sebd IPIs
-
-KVM_FEATURE_PV_POLL_CONTROL       12          host-side polling on HLT can
-                                              be disabled by writing
-                                              to msr 0x4b564d05.
-
-KVM_FEATURE_PV_SCHED_YIELD        13          guest checks this feature bit
-                                              before using paravirtualized
-                                              sched yield.
-
-KVM_FEATURE_CLOCSOURCE_STABLE_BIT 24          host will warn if no guest-side
-                                              per-cpu warps are expeced in
-                                              kvmclock
-================================= =========== ================================
-
-::
-
-      edx = an OR'ed group of (1 << flag)
-
-Where ``flag`` here is defined as below:
-
-================== ============ =================================
-flag               value        meaning
-================== ============ =================================
-KVM_HINTS_REALTIME 0            guest checks this feature bit to
-                                determine that vCPUs are never
-                                preempted for an unlimited time
-                                allowing optimizations
-================== ============ =================================
diff --git a/Documentation/virtual/kvm/devices/README b/Documentation/virtual/kvm/devices/README
deleted file mode 100644 (file)
index 34a6983..0000000
+++ /dev/null
@@ -1 +0,0 @@
-This directory contains specific device bindings for KVM_CAP_DEVICE_CTRL.
diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
deleted file mode 100644 (file)
index eeaa95b..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-ARM Virtual Interrupt Translation Service (ITS)
-===============================================
-
-Device types supported:
-  KVM_DEV_TYPE_ARM_VGIC_ITS    ARM Interrupt Translation Service Controller
-
-The ITS allows MSI(-X) interrupts to be injected into guests. This extension is
-optional.  Creating a virtual ITS controller also requires a host GICv3 (see
-arm-vgic-v3.txt), but does not depend on having physical ITS controllers.
-
-There can be multiple ITS controllers per guest, each of them has to have
-a separate, non-overlapping MMIO region.
-
-
-Groups:
-  KVM_DEV_ARM_VGIC_GRP_ADDR
-  Attributes:
-    KVM_VGIC_ITS_ADDR_TYPE (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3 ITS
-      control register frame.
-      This address needs to be 64K aligned and the region covers 128K.
-  Errors:
-    -E2BIG:  Address outside of addressable IPA range
-    -EINVAL: Incorrectly aligned address
-    -EEXIST: Address already configured
-    -EFAULT: Invalid user pointer for attr->addr.
-    -ENODEV: Incorrect attribute or the ITS is not supported.
-
-
-  KVM_DEV_ARM_VGIC_GRP_CTRL
-  Attributes:
-    KVM_DEV_ARM_VGIC_CTRL_INIT
-      request the initialization of the ITS, no additional parameter in
-      kvm_device_attr.addr.
-
-    KVM_DEV_ARM_ITS_CTRL_RESET
-      reset the ITS, no additional parameter in kvm_device_attr.addr.
-      See "ITS Reset State" section.
-
-    KVM_DEV_ARM_ITS_SAVE_TABLES
-      save the ITS table data into guest RAM, at the location provisioned
-      by the guest in corresponding registers/table entries.
-
-      The layout of the tables in guest memory defines an ABI. The entries
-      are laid out in little endian format as described in the last paragraph.
-
-    KVM_DEV_ARM_ITS_RESTORE_TABLES
-      restore the ITS tables from guest RAM to ITS internal structures.
-
-      The GICV3 must be restored before the ITS and all ITS registers but
-      the GITS_CTLR must be restored before restoring the ITS tables.
-
-      The GITS_IIDR read-only register must also be restored before
-      calling KVM_DEV_ARM_ITS_RESTORE_TABLES as the IIDR revision field
-      encodes the ABI revision.
-
-      The expected ordering when restoring the GICv3/ITS is described in section
-      "ITS Restore Sequence".
-
-  Errors:
-    -ENXIO:  ITS not properly configured as required prior to setting
-             this attribute
-    -ENOMEM: Memory shortage when allocating ITS internal data
-    -EINVAL: Inconsistent restored data
-    -EFAULT: Invalid guest ram access
-    -EBUSY:  One or more VCPUS are running
-    -EACCES: The virtual ITS is backed by a physical GICv4 ITS, and the
-            state is not available
-
-  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
-  Attributes:
-      The attr field of kvm_device_attr encodes the offset of the
-      ITS register, relative to the ITS control frame base address
-      (ITS_base).
-
-      kvm_device_attr.addr points to a __u64 value whatever the width
-      of the addressed register (32/64 bits). 64 bit registers can only
-      be accessed with full length.
-
-      Writes to read-only registers are ignored by the kernel except for:
-      - GITS_CREADR. It must be restored otherwise commands in the queue
-        will be re-executed after restoring CWRITER. GITS_CREADR must be
-        restored before restoring the GITS_CTLR which is likely to enable the
-        ITS. Also it must be restored after GITS_CBASER since a write to
-        GITS_CBASER resets GITS_CREADR.
-      - GITS_IIDR. The Revision field encodes the table layout ABI revision.
-        In the future we might implement direct injection of virtual LPIs.
-        This will require an upgrade of the table layout and an evolution of
-        the ABI. GITS_IIDR must be restored before calling
-        KVM_DEV_ARM_ITS_RESTORE_TABLES.
-
-      For other registers, getting or setting a register has the same
-      effect as reading/writing the register on real hardware.
-  Errors:
-    -ENXIO: Offset does not correspond to any supported register
-    -EFAULT: Invalid user pointer for attr->addr
-    -EINVAL: Offset is not 64-bit aligned
-    -EBUSY: one or more VCPUS are running
-
- ITS Restore Sequence:
- -------------------------
-
-The following ordering must be followed when restoring the GIC and the ITS:
-a) restore all guest memory and create vcpus
-b) restore all redistributors
-c) provide the ITS base address
-   (KVM_DEV_ARM_VGIC_GRP_ADDR)
-d) restore the ITS in the following order:
-   1. Restore GITS_CBASER
-   2. Restore all other GITS_ registers, except GITS_CTLR!
-   3. Load the ITS table data (KVM_DEV_ARM_ITS_RESTORE_TABLES)
-   4. Restore GITS_CTLR
-
-Then vcpus can be started.
-
- ITS Table ABI REV0:
- -------------------
-
- Revision 0 of the ABI only supports the features of a virtual GICv3, and does
- not support a virtual GICv4 with support for direct injection of virtual
- interrupts for nested hypervisors.
-
- The device table and ITT are indexed by the DeviceID and EventID,
- respectively. The collection table is not indexed by CollectionID, and the
- entries in the collection are listed in no particular order.
- All entries are 8 bytes.
-
- Device Table Entry (DTE):
-
- bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
- values:   | V |   next    | ITT_addr |  Size   |
-
- where;
- - V indicates whether the entry is valid. If not, other fields
-   are not meaningful.
- - next: equals to 0 if this entry is the last one; otherwise it
-   corresponds to the DeviceID offset to the next DTE, capped by
-   2^14 -1.
- - ITT_addr matches bits [51:8] of the ITT address (256 Byte aligned).
- - Size specifies the supported number of bits for the EventID,
-   minus one
-
- Collection Table Entry (CTE):
-
- bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
- values:   | V |    RES0    |  RDBase   |    ICID     |
-
- where:
- - V indicates whether the entry is valid. If not, other fields are
-   not meaningful.
- - RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
- - RDBase is the PE number (GICR_TYPER.Processor_Number semantic),
- - ICID is the collection ID
-
- Interrupt Translation Entry (ITE):
-
- bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
- values:   |    next   |   pINTID  |  ICID    |
-
- where:
- - next: equals to 0 if this entry is the last one; otherwise it corresponds
-   to the EventID offset to the next ITE capped by 2^16 -1.
- - pINTID is the physical LPI ID; if zero, it means the entry is not valid
-   and other fields are not meaningful.
- - ICID is the collection ID
-
- ITS Reset State:
- ----------------
-
-RESET returns the ITS to the same state that it was when first created and
-initialized. When the RESET command returns, the following things are
-guaranteed:
-
-- The ITS is not enabled and quiescent
-  GITS_CTLR.Enabled = 0 .Quiescent=1
-- There is no internally cached state
-- No collection or device table are used
-  GITS_BASER<n>.Valid = 0
-- GITS_CBASER = 0, GITS_CREADR = 0, GITS_CWRITER = 0
-- The ABI version is unchanged and remains the one set when the ITS
-  device was first created.
diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
deleted file mode 100644 (file)
index ff290b4..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-ARM Virtual Generic Interrupt Controller v3 and later (VGICv3)
-==============================================================
-
-
-Device types supported:
-  KVM_DEV_TYPE_ARM_VGIC_V3     ARM Generic Interrupt Controller v3.0
-
-Only one VGIC instance may be instantiated through this API.  The created VGIC
-will act as the VM interrupt controller, requiring emulated user-space devices
-to inject interrupts to the VGIC instead of directly to CPUs.  It is not
-possible to create both a GICv3 and GICv2 on the same VM.
-
-Creating a guest GICv3 device requires a host GICv3 as well.
-
-
-Groups:
-  KVM_DEV_ARM_VGIC_GRP_ADDR
-  Attributes:
-    KVM_VGIC_V3_ADDR_TYPE_DIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3 distributor
-      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned and the region covers 64 KByte.
-
-    KVM_VGIC_V3_ADDR_TYPE_REDIST (rw, 64-bit)
-      Base address in the guest physical address space of the GICv3
-      redistributor register mappings. There are two 64K pages for each
-      VCPU and all of the redistributor pages are contiguous.
-      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-      This address needs to be 64K aligned.
-
-    KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION (rw, 64-bit)
-      The attribute data pointed to by kvm_device_attr.addr is a __u64 value:
-      bits:     | 63   ....  52  |  51   ....   16 | 15 - 12  |11 - 0
-      values:   |     count      |       base      |  flags   | index
-      - index encodes the unique redistributor region index
-      - flags: reserved for future use, currently 0
-      - base field encodes bits [51:16] of the guest physical base address
-        of the first redistributor in the region.
-      - count encodes the number of redistributors in the region. Must be
-        greater than 0.
-      There are two 64K pages for each redistributor in the region and
-      redistributors are laid out contiguously within the region. Regions
-      are filled with redistributors in the index order. The sum of all
-      region count fields must be greater than or equal to the number of
-      VCPUs. Redistributor regions must be registered in the incremental
-      index order, starting from index 0.
-      The characteristics of a specific redistributor region can be read
-      by presetting the index field in the attr data.
-      Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
-
-  It is invalid to mix calls with KVM_VGIC_V3_ADDR_TYPE_REDIST and
-  KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attributes.
-
-  Errors:
-    -E2BIG:  Address outside of addressable IPA range
-    -EINVAL: Incorrectly aligned address, bad redistributor region
-             count/index, mixed redistributor region attribute usage
-    -EEXIST: Address already configured
-    -ENOENT: Attempt to read the characteristics of a non existing
-             redistributor region
-    -ENXIO:  The group or attribute is unknown/unsupported for this device
-             or hardware support is missing.
-    -EFAULT: Invalid user pointer for attr->addr.
-
-
-  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
-  KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63   ....  32  |  31   ....    0 |
-    values:   |      mpidr     |      offset     |
-
-    All distributor regs are (rw, 32-bit) and kvm_device_attr.addr points to a
-    __u32 value.  64-bit registers must be accessed by separately accessing the
-    lower and higher word.
-
-    Writes to read-only registers are ignored by the kernel.
-
-    KVM_DEV_ARM_VGIC_GRP_DIST_REGS accesses the main distributor registers.
-    KVM_DEV_ARM_VGIC_GRP_REDIST_REGS accesses the redistributor of the CPU
-    specified by the mpidr.
-
-    The offset is relative to the "[Re]Distributor base address" as defined
-    in the GICv3/4 specs.  Getting or setting such a register has the same
-    effect as reading or writing the register on real hardware, except for the
-    following registers: GICD_STATUSR, GICR_STATUSR, GICD_ISPENDR,
-    GICR_ISPENDR0, GICD_ICPENDR, and GICR_ICPENDR0.  These registers behave
-    differently when accessed via this interface compared to their
-    architecturally defined behavior to allow software a full view of the
-    VGIC's internal state.
-
-    The mpidr field is used to specify which
-    redistributor is accessed.  The mpidr is ignored for the distributor.
-
-    The mpidr encoding is based on the affinity information in the
-    architecture defined MPIDR, and the field is encoded as follows:
-      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
-      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
-
-    Note that distributor fields are not banked, but return the same value
-    regardless of the mpidr used to access the register.
-
-    GICD_IIDR.Revision is updated when the KVM implementation is changed in a
-    way directly observable by the guest or userspace.  Userspace should read
-    GICD_IIDR from KVM and write back the read value to confirm its expected
-    behavior is aligned with the KVM implementation.  Userspace should set
-    GICD_IIDR before setting any other registers to ensure the expected
-    behavior.
-
-
-    The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
-    that a write of a clear bit has no effect, whereas a write with a set bit
-    clears that value.  To allow userspace to freely set the values of these two
-    registers, setting the attributes with the register offsets for these two
-    registers simply sets the non-reserved bits to the value written.
-
-
-    Accesses (reads and writes) to the GICD_ISPENDR register region and
-    GICR_ISPENDR0 registers get/set the value of the latched pending state for
-    the interrupts.
-
-    This is identical to the value returned by a guest read from ISPENDR for an
-    edge triggered interrupt, but may differ for level triggered interrupts.
-    For edge triggered interrupts, once an interrupt becomes pending (whether
-    because of an edge detected on the input line or because of a guest write
-    to ISPENDR) this state is "latched", and only cleared when either the
-    interrupt is activated or when the guest writes to ICPENDR. A level
-    triggered interrupt may be pending either because the level input is held
-    high by a device, or because of a guest write to the ISPENDR register. Only
-    ISPENDR writes are latched; if the device lowers the line level then the
-    interrupt is no longer pending unless the guest also wrote to ISPENDR, and
-    conversely writes to ICPENDR or activations of the interrupt do not clear
-    the pending status if the line level is still being held high.  (These
-    rules are documented in the GICv3 specification descriptions of the ICPENDR
-    and ISPENDR registers.) For a level triggered interrupt the value accessed
-    here is that of the latch which is set by ISPENDR and cleared by ICPENDR or
-    interrupt activation, whereas the value returned by a guest read from
-    ISPENDR is the logical OR of the latch value and the input line level.
-
-    Raw access to the latch state is provided to userspace so that it can save
-    and restore the entire GIC internal state (which is defined by the
-    combination of the current input line level and the latch state, and cannot
-    be deduced from purely the line level and the value of the ISPENDR
-    registers).
-
-    Accesses to GICD_ICPENDR register region and GICR_ICPENDR0 registers have
-    RAZ/WI semantics, meaning that reads always return 0 and writes are always
-    ignored.
-
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: One or more VCPUs are running
-
-
-  KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63      ....       32 | 31  ....  16 | 15  ....  0 |
-    values:   |         mpidr         |      RES     |    instr    |
-
-    The mpidr field encodes the CPU ID based on the affinity information in the
-    architecture defined MPIDR, and the field is encoded as follows:
-      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
-      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
-
-    The instr field encodes the system register to access based on the fields
-    defined in the A64 instruction set encoding for system register access
-    (RES means the bits are reserved for future use and should be zero):
-
-      | 15 ... 14 | 13 ... 11 | 10 ... 7 | 6 ... 3 | 2 ... 0 |
-      |   Op 0    |    Op1    |    CRn   |   CRm   |   Op2   |
-
-    All system regs accessed through this API are (rw, 64-bit) and
-    kvm_device_attr.addr points to a __u64 value.
-
-    KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS accesses the CPU interface registers for the
-    CPU specified by the mpidr field.
-
-    CPU interface registers access is not implemented for AArch32 mode.
-    Error -ENXIO is returned when accessed in AArch32 mode.
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: VCPU is running
-    -EINVAL: Invalid mpidr or register value supplied
-
-
-  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
-  Attributes:
-    A value describing the number of interrupts (SGI, PPI and SPI) for
-    this GIC instance, ranging from 64 to 1024, in increments of 32.
-
-    kvm_device_attr.addr points to a __u32 value.
-
-  Errors:
-    -EINVAL: Value set is out of the expected range
-    -EBUSY: Value has already be set.
-
-
-  KVM_DEV_ARM_VGIC_GRP_CTRL
-  Attributes:
-    KVM_DEV_ARM_VGIC_CTRL_INIT
-      request the initialization of the VGIC, no additional parameter in
-      kvm_device_attr.addr.
-    KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES
-      save all LPI pending bits into guest RAM pending tables.
-
-      The first kB of the pending table is not altered by this operation.
-  Errors:
-    -ENXIO: VGIC not properly configured as required prior to calling
-     this attribute
-    -ENODEV: no online VCPU
-    -ENOMEM: memory shortage when allocating vgic internal data
-    -EFAULT: Invalid guest ram access
-    -EBUSY:  One or more VCPUS are running
-
-
-  KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO
-  Attributes:
-    The attr field of kvm_device_attr encodes the following values:
-    bits:     | 63      ....       32 | 31   ....    10 | 9  ....  0 |
-    values:   |         mpidr         |      info       |   vINTID   |
-
-    The vINTID specifies which set of IRQs is reported on.
-
-    The info field specifies which information userspace wants to get or set
-    using this interface.  Currently we support the following info values:
-
-      VGIC_LEVEL_INFO_LINE_LEVEL:
-       Get/Set the input level of the IRQ line for a set of 32 contiguously
-       numbered interrupts.
-       vINTID must be a multiple of 32.
-
-       kvm_device_attr.addr points to a __u32 value which will contain a
-       bitmap where a set bit means the interrupt level is asserted.
-
-       Bit[n] indicates the status for interrupt vINTID + n.
-
-    SGIs and any interrupt with a higher ID than the number of interrupts
-    supported, will be RAZ/WI.  LPIs are always edge-triggered and are
-    therefore not supported by this interface.
-
-    PPIs are reported per VCPU as specified in the mpidr field, and SPIs are
-    reported with the same value regardless of the mpidr specified.
-
-    The mpidr field encodes the CPU ID based on the affinity information in the
-    architecture defined MPIDR, and the field is encoded as follows:
-      | 63 .... 56 | 55 .... 48 | 47 .... 40 | 39 .... 32 |
-      |    Aff3    |    Aff2    |    Aff1    |    Aff0    |
-  Errors:
-    -EINVAL: vINTID is not multiple of 32 or
-     info field is not VGIC_LEVEL_INFO_LINE_LEVEL
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
deleted file mode 100644 (file)
index 97b6518..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-ARM Virtual Generic Interrupt Controller v2 (VGIC)
-==================================================
-
-Device types supported:
-  KVM_DEV_TYPE_ARM_VGIC_V2     ARM Generic Interrupt Controller v2.0
-
-Only one VGIC instance may be instantiated through either this API or the
-legacy KVM_CREATE_IRQCHIP API.  The created VGIC will act as the VM interrupt
-controller, requiring emulated user-space devices to inject interrupts to the
-VGIC instead of directly to CPUs.
-
-GICv3 implementations with hardware compatibility support allow creating a
-guest GICv2 through this interface.  For information on creating a guest GICv3
-device and guest ITS devices, see arm-vgic-v3.txt.  It is not possible to
-create both a GICv3 and GICv2 device on the same VM.
-
-
-Groups:
-  KVM_DEV_ARM_VGIC_GRP_ADDR
-  Attributes:
-    KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
-      Base address in the guest physical address space of the GIC distributor
-      register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
-      This address needs to be 4K aligned and the region covers 4 KByte.
-
-    KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
-      Base address in the guest physical address space of the GIC virtual cpu
-      interface register mappings. Only valid for KVM_DEV_TYPE_ARM_VGIC_V2.
-      This address needs to be 4K aligned and the region covers 4 KByte.
-  Errors:
-    -E2BIG:  Address outside of addressable IPA range
-    -EINVAL: Incorrectly aligned address
-    -EEXIST: Address already configured
-    -ENXIO:  The group or attribute is unknown/unsupported for this device
-             or hardware support is missing.
-    -EFAULT: Invalid user pointer for attr->addr.
-
-  KVM_DEV_ARM_VGIC_GRP_DIST_REGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
-    values:   |    reserved   | vcpu_index |      offset     |
-
-    All distributor regs are (rw, 32-bit)
-
-    The offset is relative to the "Distributor base address" as defined in the
-    GICv2 specs.  Getting or setting such a register has the same effect as
-    reading or writing the register on the actual hardware from the cpu whose
-    index is specified with the vcpu_index field.  Note that most distributor
-    fields are not banked, but return the same value regardless of the
-    vcpu_index used to access the register.
-
-    GICD_IIDR.Revision is updated when the KVM implementation of an emulated
-    GICv2 is changed in a way directly observable by the guest or userspace.
-    Userspace should read GICD_IIDR from KVM and write back the read value to
-    confirm its expected behavior is aligned with the KVM implementation.
-    Userspace should set GICD_IIDR before setting any other registers (both
-    KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_CPU_REGS) to ensure
-    the expected behavior. Unless GICD_IIDR has been set from userspace, writes
-    to the interrupt group registers (GICD_IGROUPR) are ignored.
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: One or more VCPUs are running
-    -EINVAL: Invalid vcpu_index supplied
-
-  KVM_DEV_ARM_VGIC_GRP_CPU_REGS
-  Attributes:
-    The attr field of kvm_device_attr encodes two values:
-    bits:     | 63   ....  40 | 39 ..  32  |  31   ....    0 |
-    values:   |    reserved   | vcpu_index |      offset     |
-
-    All CPU interface regs are (rw, 32-bit)
-
-    The offset specifies the offset from the "CPU interface base address" as
-    defined in the GICv2 specs.  Getting or setting such a register has the
-    same effect as reading or writing the register on the actual hardware.
-
-    The Active Priorities Registers APRn are implementation defined, so we set a
-    fixed format for our implementation that fits with the model of a "GICv2
-    implementation without the security extensions" which we present to the
-    guest.  This interface always exposes four register APR[0-3] describing the
-    maximum possible 128 preemption levels.  The semantics of the register
-    indicate if any interrupts in a given preemption level are in the active
-    state by setting the corresponding bit.
-
-    Thus, preemption level X has one or more active interrupts if and only if:
-
-      APRn[X mod 32] == 0b1,  where n = X / 32
-
-    Bits for undefined preemption levels are RAZ/WI.
-
-    Note that this differs from a CPU's view of the APRs on hardware in which
-    a GIC without the security extensions expose group 0 and group 1 active
-    priorities in separate register groups, whereas we show a combined view
-    similar to GICv2's GICH_APR.
-
-    For historical reasons and to provide ABI compatibility with userspace we
-    export the GICC_PMR register in the format of the GICH_VMCR.VMPriMask
-    field in the lower 5 bits of a word, meaning that userspace must always
-    use the lower 5 bits to communicate with the KVM device and must shift the
-    value left by 3 places to obtain the actual priority mask level.
-
-  Errors:
-    -ENXIO: Getting or setting this register is not yet supported
-    -EBUSY: One or more VCPUs are running
-    -EINVAL: Invalid vcpu_index supplied
-
-  KVM_DEV_ARM_VGIC_GRP_NR_IRQS
-  Attributes:
-    A value describing the number of interrupts (SGI, PPI and SPI) for
-    this GIC instance, ranging from 64 to 1024, in increments of 32.
-
-  Errors:
-    -EINVAL: Value set is out of the expected range
-    -EBUSY: Value has already be set, or GIC has already been initialized
-            with default values.
-
-  KVM_DEV_ARM_VGIC_GRP_CTRL
-  Attributes:
-    KVM_DEV_ARM_VGIC_CTRL_INIT
-      request the initialization of the VGIC or ITS, no additional parameter
-      in kvm_device_attr.addr.
-  Errors:
-    -ENXIO: VGIC not properly configured as required prior to calling
-     this attribute
-    -ENODEV: no online VCPU
-    -ENOMEM: memory shortage when allocating vgic internal data
diff --git a/Documentation/virtual/kvm/devices/mpic.txt b/Documentation/virtual/kvm/devices/mpic.txt
deleted file mode 100644 (file)
index 8257397..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-MPIC interrupt controller
-=========================
-
-Device types supported:
-  KVM_DEV_TYPE_FSL_MPIC_20     Freescale MPIC v2.0
-  KVM_DEV_TYPE_FSL_MPIC_42     Freescale MPIC v4.2
-
-Only one MPIC instance, of any type, may be instantiated.  The created
-MPIC will act as the system interrupt controller, connecting to each
-vcpu's interrupt inputs.
-
-Groups:
-  KVM_DEV_MPIC_GRP_MISC
-  Attributes:
-    KVM_DEV_MPIC_BASE_ADDR (rw, 64-bit)
-      Base address of the 256 KiB MPIC register space.  Must be
-      naturally aligned.  A value of zero disables the mapping.
-      Reset value is zero.
-
-  KVM_DEV_MPIC_GRP_REGISTER (rw, 32-bit)
-    Access an MPIC register, as if the access were made from the guest.
-    "attr" is the byte offset into the MPIC register space.  Accesses
-    must be 4-byte aligned.
-
-    MSIs may be signaled by using this attribute group to write
-    to the relevant MSIIR.
-
-  KVM_DEV_MPIC_GRP_IRQ_ACTIVE (rw, 32-bit)
-    IRQ input line for each standard openpic source.  0 is inactive and 1
-    is active, regardless of interrupt sense.
-
-    For edge-triggered interrupts:  Writing 1 is considered an activating
-    edge, and writing 0 is ignored.  Reading returns 1 if a previously
-    signaled edge has not been acknowledged, and 0 otherwise.
-
-    "attr" is the IRQ number.  IRQ numbers for standard sources are the
-    byte offset of the relevant IVPR from EIVPR0, divided by 32.
-
-IRQ Routing:
-
-  The MPIC emulation supports IRQ routing. Only a single MPIC device can
-  be instantiated. Once that device has been created, it's available as
-  irqchip id 0.
-
-  This irqchip 0 has 256 interrupt pins, which expose the interrupts in
-  the main array of interrupt sources (a.k.a. "SRC" interrupts).
-
-  The numbering is the same as the MPIC device tree binding -- based on
-  the register offset from the beginning of the sources array, without
-  regard to any subdivisions in chip documentation such as "internal"
-  or "external" interrupts.
-
-  Access to non-SRC interrupts is not implemented through IRQ routing mechanisms.
diff --git a/Documentation/virtual/kvm/devices/s390_flic.txt b/Documentation/virtual/kvm/devices/s390_flic.txt
deleted file mode 100644 (file)
index a4e20a0..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-FLIC (floating interrupt controller)
-====================================
-
-FLIC handles floating (non per-cpu) interrupts, i.e. I/O, service and some
-machine check interruptions. All interrupts are stored in a per-vm list of
-pending interrupts. FLIC performs operations on this list.
-
-Only one FLIC instance may be instantiated.
-
-FLIC provides support to
-- add interrupts (KVM_DEV_FLIC_ENQUEUE)
-- inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS)
-- purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS)
-- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
-- enable/disable for the guest transparent async page faults
-- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
-- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
-- inject adapter interrupts on a specified adapter (KVM_DEV_FLIC_AIRQ_INJECT)
-- get/set all AIS mode states (KVM_DEV_FLIC_AISM_ALL)
-
-Groups:
-  KVM_DEV_FLIC_ENQUEUE
-    Passes a buffer and length into the kernel which are then injected into
-    the list of pending interrupts.
-    attr->addr contains the pointer to the buffer and attr->attr contains
-    the length of the buffer.
-    The format of the data structure kvm_s390_irq as it is copied from userspace
-    is defined in usr/include/linux/kvm.h.
-
-  KVM_DEV_FLIC_GET_ALL_IRQS
-    Copies all floating interrupts into a buffer provided by userspace.
-    When the buffer is too small it returns -ENOMEM, which is the indication
-    for userspace to try again with a bigger buffer.
-    -ENOBUFS is returned when the allocation of a kernelspace buffer has
-    failed.
-    -EFAULT is returned when copying data to userspace failed.
-    All interrupts remain pending, i.e. are not deleted from the list of
-    currently pending interrupts.
-    attr->addr contains the userspace address of the buffer into which all
-    interrupt data will be copied.
-    attr->attr contains the size of the buffer in bytes.
-
-  KVM_DEV_FLIC_CLEAR_IRQS
-    Simply deletes all elements from the list of currently pending floating
-    interrupts.  No interrupts are injected into the guest.
-
-  KVM_DEV_FLIC_CLEAR_IO_IRQ
-    Deletes one (if any) I/O interrupt for a subchannel identified by the
-    subsystem identification word passed via the buffer specified by
-    attr->addr (address) and attr->attr (length).
-
-  KVM_DEV_FLIC_APF_ENABLE
-    Enables async page faults for the guest. So in case of a major page fault
-    the host is allowed to handle this async and continues the guest.
-
-  KVM_DEV_FLIC_APF_DISABLE_WAIT
-    Disables async page faults for the guest and waits until already pending
-    async page faults are done. This is necessary to trigger a completion interrupt
-    for every init interrupt before migrating the interrupt list.
-
-  KVM_DEV_FLIC_ADAPTER_REGISTER
-    Register an I/O adapter interrupt source. Takes a kvm_s390_io_adapter
-    describing the adapter to register:
-
-struct kvm_s390_io_adapter {
-       __u32 id;
-       __u8 isc;
-       __u8 maskable;
-       __u8 swap;
-       __u8 flags;
-};
-
-   id contains the unique id for the adapter, isc the I/O interruption subclass
-   to use, maskable whether this adapter may be masked (interrupts turned off),
-   swap whether the indicators need to be byte swapped, and flags contains
-   further characteristics of the adapter.
-   Currently defined values for 'flags' are:
-   - KVM_S390_ADAPTER_SUPPRESSIBLE: adapter is subject to AIS
-     (adapter-interrupt-suppression) facility. This flag only has an effect if
-     the AIS capability is enabled.
-   Unknown flag values are ignored.
-
-
-  KVM_DEV_FLIC_ADAPTER_MODIFY
-    Modifies attributes of an existing I/O adapter interrupt source. Takes
-    a kvm_s390_io_adapter_req specifying the adapter and the operation:
-
-struct kvm_s390_io_adapter_req {
-       __u32 id;
-       __u8 type;
-       __u8 mask;
-       __u16 pad0;
-       __u64 addr;
-};
-
-    id specifies the adapter and type the operation. The supported operations
-    are:
-
-    KVM_S390_IO_ADAPTER_MASK
-      mask or unmask the adapter, as specified in mask
-
-    KVM_S390_IO_ADAPTER_MAP
-      perform a gmap translation for the guest address provided in addr,
-      pin a userspace page for the translated address and add it to the
-      list of mappings
-      Note: A new mapping will be created unconditionally; therefore,
-            the calling code should avoid making duplicate mappings.
-
-    KVM_S390_IO_ADAPTER_UNMAP
-      release a userspace page for the translated address specified in addr
-      from the list of mappings
-
-  KVM_DEV_FLIC_AISM
-    modify the adapter-interruption-suppression mode for a given isc if the
-    AIS capability is enabled. Takes a kvm_s390_ais_req describing:
-
-struct kvm_s390_ais_req {
-       __u8 isc;
-       __u16 mode;
-};
-
-    isc contains the target I/O interruption subclass, mode the target
-    adapter-interruption-suppression mode. The following modes are
-    currently supported:
-    - KVM_S390_AIS_MODE_ALL: ALL-Interruptions Mode, i.e. airq injection
-      is always allowed;
-    - KVM_S390_AIS_MODE_SINGLE: SINGLE-Interruption Mode, i.e. airq
-      injection is only allowed once and the following adapter interrupts
-      will be suppressed until the mode is set again to ALL-Interruptions
-      or SINGLE-Interruption mode.
-
-  KVM_DEV_FLIC_AIRQ_INJECT
-    Inject adapter interrupts on a specified adapter.
-    attr->attr contains the unique id for the adapter, which allows for
-    adapter-specific checks and actions.
-    For adapters subject to AIS, handle the airq injection suppression for
-    an isc according to the adapter-interruption-suppression mode on condition
-    that the AIS capability is enabled.
-
-  KVM_DEV_FLIC_AISM_ALL
-    Gets or sets the adapter-interruption-suppression mode for all ISCs. Takes
-    a kvm_s390_ais_all describing:
-
-struct kvm_s390_ais_all {
-       __u8 simm; /* Single-Interruption-Mode mask */
-       __u8 nimm; /* No-Interruption-Mode mask *
-};
-
-    simm contains Single-Interruption-Mode mask for all ISCs, nimm contains
-    No-Interruption-Mode mask for all ISCs. Each bit in simm and nimm corresponds
-    to an ISC (MSB0 bit 0 to ISC 0 and so on). The combination of simm bit and
-    nimm bit presents AIS mode for a ISC.
-
-    KVM_DEV_FLIC_AISM_ALL is indicated by KVM_CAP_S390_AIS_MIGRATION.
-
-Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
-FLIC with an unknown group or attribute gives the error code EINVAL (instead of
-ENXIO, as specified in the API documentation). It is not possible to conclude
-that a FLIC operation is unavailable based on the error code resulting from a
-usage attempt.
-
-Note: The KVM_DEV_FLIC_CLEAR_IO_IRQ ioctl will return EINVAL in case a zero
-schid is specified.
diff --git a/Documentation/virtual/kvm/devices/vcpu.txt b/Documentation/virtual/kvm/devices/vcpu.txt
deleted file mode 100644 (file)
index 2b5dab1..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-Generic vcpu interface
-====================================
-
-The virtual cpu "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
-KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same struct
-kvm_device_attr as other devices, but targets VCPU-wide settings and controls.
-
-The groups and attributes per virtual cpu, if any, are architecture specific.
-
-1. GROUP: KVM_ARM_VCPU_PMU_V3_CTRL
-Architectures: ARM64
-
-1.1. ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_IRQ
-Parameters: in kvm_device_attr.addr the address for PMU overflow interrupt is a
-            pointer to an int
-Returns: -EBUSY: The PMU overflow interrupt is already set
-         -ENXIO: The overflow interrupt not set when attempting to get it
-         -ENODEV: PMUv3 not supported
-         -EINVAL: Invalid PMU overflow interrupt number supplied or
-                  trying to set the IRQ number without using an in-kernel
-                  irqchip.
-
-A value describing the PMUv3 (Performance Monitor Unit v3) overflow interrupt
-number for this vcpu. This interrupt could be a PPI or SPI, but the interrupt
-type must be same for each vcpu. As a PPI, the interrupt number is the same for
-all vcpus, while as an SPI it must be a separate number per vcpu.
-
-1.2 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_INIT
-Parameters: no additional parameter in kvm_device_attr.addr
-Returns: -ENODEV: PMUv3 not supported or GIC not initialized
-         -ENXIO: PMUv3 not properly configured or in-kernel irqchip not
-                 configured as required prior to calling this attribute
-         -EBUSY: PMUv3 already initialized
-
-Request the initialization of the PMUv3.  If using the PMUv3 with an in-kernel
-virtual GIC implementation, this must be done after initializing the in-kernel
-irqchip.
-
-
-2. GROUP: KVM_ARM_VCPU_TIMER_CTRL
-Architectures: ARM,ARM64
-
-2.1. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_VTIMER
-2.2. ATTRIBUTE: KVM_ARM_VCPU_TIMER_IRQ_PTIMER
-Parameters: in kvm_device_attr.addr the address for the timer interrupt is a
-            pointer to an int
-Returns: -EINVAL: Invalid timer interrupt number
-         -EBUSY:  One or more VCPUs has already run
-
-A value describing the architected timer interrupt number when connected to an
-in-kernel virtual GIC.  These must be a PPI (16 <= intid < 32).  Setting the
-attribute overrides the default values (see below).
-
-KVM_ARM_VCPU_TIMER_IRQ_VTIMER: The EL1 virtual timer intid (default: 27)
-KVM_ARM_VCPU_TIMER_IRQ_PTIMER: The EL1 physical timer intid (default: 30)
-
-Setting the same PPI for different timers will prevent the VCPUs from running.
-Setting the interrupt number on a VCPU configures all VCPUs created at that
-time to use the number provided for a given timer, overwriting any previously
-configured values on other VCPUs.  Userspace should configure the interrupt
-numbers on at least one VCPU after creating all VCPUs and before running any
-VCPUs.
diff --git a/Documentation/virtual/kvm/devices/vfio.txt b/Documentation/virtual/kvm/devices/vfio.txt
deleted file mode 100644 (file)
index 528c77c..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-VFIO virtual device
-===================
-
-Device types supported:
-  KVM_DEV_TYPE_VFIO
-
-Only one VFIO instance may be created per VM.  The created device
-tracks VFIO groups in use by the VM and features of those groups
-important to the correctness and acceleration of the VM.  As groups
-are enabled and disabled for use by the VM, KVM should be updated
-about their presence.  When registered with KVM, a reference to the
-VFIO-group is held by KVM.
-
-Groups:
-  KVM_DEV_VFIO_GROUP
-
-KVM_DEV_VFIO_GROUP attributes:
-  KVM_DEV_VFIO_GROUP_ADD: Add a VFIO group to VFIO-KVM device tracking
-       kvm_device_attr.addr points to an int32_t file descriptor
-       for the VFIO group.
-  KVM_DEV_VFIO_GROUP_DEL: Remove a VFIO group from VFIO-KVM device tracking
-       kvm_device_attr.addr points to an int32_t file descriptor
-       for the VFIO group.
-  KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE: attaches a guest visible TCE table
-       allocated by sPAPR KVM.
-       kvm_device_attr.addr points to a struct:
-
-       struct kvm_vfio_spapr_tce {
-               __s32   groupfd;
-               __s32   tablefd;
-       };
-
-       where
-       @groupfd is a file descriptor for a VFIO group;
-       @tablefd is a file descriptor for a TCE table allocated via
-               KVM_CREATE_SPAPR_TCE.
diff --git a/Documentation/virtual/kvm/devices/vm.txt b/Documentation/virtual/kvm/devices/vm.txt
deleted file mode 100644 (file)
index 4ffb82b..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-Generic vm interface
-====================================
-
-The virtual machine "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
-KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same
-struct kvm_device_attr as other devices, but targets VM-wide settings
-and controls.
-
-The groups and attributes per virtual machine, if any, are architecture
-specific.
-
-1. GROUP: KVM_S390_VM_MEM_CTRL
-Architectures: s390
-
-1.1. ATTRIBUTE: KVM_S390_VM_MEM_ENABLE_CMMA
-Parameters: none
-Returns: -EBUSY if a vcpu is already defined, otherwise 0
-
-Enables Collaborative Memory Management Assist (CMMA) for the virtual machine.
-
-1.2. ATTRIBUTE: KVM_S390_VM_MEM_CLR_CMMA
-Parameters: none
-Returns: -EINVAL if CMMA was not enabled
-         0 otherwise
-
-Clear the CMMA status for all guest pages, so any pages the guest marked
-as unused are again used any may not be reclaimed by the host.
-
-1.3. ATTRIBUTE KVM_S390_VM_MEM_LIMIT_SIZE
-Parameters: in attr->addr the address for the new limit of guest memory
-Returns: -EFAULT if the given address is not accessible
-         -EINVAL if the virtual machine is of type UCONTROL
-         -E2BIG if the given guest memory is to big for that machine
-         -EBUSY if a vcpu is already defined
-         -ENOMEM if not enough memory is available for a new shadow guest mapping
-          0 otherwise
-
-Allows userspace to query the actual limit and set a new limit for
-the maximum guest memory size. The limit will be rounded up to
-2048 MB, 4096 GB, 8192 TB respectively, as this limit is governed by
-the number of page table levels. In the case that there is no limit we will set
-the limit to KVM_S390_NO_MEM_LIMIT (U64_MAX).
-
-2. GROUP: KVM_S390_VM_CPU_MODEL
-Architectures: s390
-
-2.1. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE (r/o)
-
-Allows user space to retrieve machine and kvm specific cpu related information:
-
-struct kvm_s390_vm_cpu_machine {
-       __u64 cpuid;           # CPUID of host
-       __u32 ibc;             # IBC level range offered by host
-       __u8  pad[4];
-       __u64 fac_mask[256];   # set of cpu facilities enabled by KVM
-       __u64 fac_list[256];   # set of cpu facilities offered by host
-}
-
-Parameters: address of buffer to store the machine related cpu data
-            of type struct kvm_s390_vm_cpu_machine*
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           -ENOMEM if not enough memory is available to process the ioctl
-           0 in case of success
-
-2.2. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR (r/w)
-
-Allows user space to retrieve or request to change cpu related information for a vcpu:
-
-struct kvm_s390_vm_cpu_processor {
-       __u64 cpuid;           # CPUID currently (to be) used by this vcpu
-       __u16 ibc;             # IBC level currently (to be) used by this vcpu
-       __u8  pad[6];
-       __u64 fac_list[256];   # set of cpu facilities currently (to be) used
-                              # by this vcpu
-}
-
-KVM does not enforce or limit the cpu model data in any form. Take the information
-retrieved by means of KVM_S390_VM_CPU_MACHINE as hint for reasonable configuration
-setups. Instruction interceptions triggered by additionally set facility bits that
-are not handled by KVM need to by imlemented in the VM driver code.
-
-Parameters: address of buffer to store/set the processor related cpu
-           data of type struct kvm_s390_vm_cpu_processor*.
-Returns:    -EBUSY in case 1 or more vcpus are already activated (only in write case)
-           -EFAULT if the given address is not accessible from kernel space
-           -ENOMEM if not enough memory is available to process the ioctl
-           0 in case of success
-
-2.3. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_FEAT (r/o)
-
-Allows user space to retrieve available cpu features. A feature is available if
-provided by the hardware and supported by kvm. In theory, cpu features could
-even be completely emulated by kvm.
-
-struct kvm_s390_vm_cpu_feat {
-        __u64 feat[16]; # Bitmap (1 = feature available), MSB 0 bit numbering
-};
-
-Parameters: address of a buffer to load the feature list from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           0 in case of success.
-
-2.4. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_FEAT (r/w)
-
-Allows user space to retrieve or change enabled cpu features for all VCPUs of a
-VM. Features that are not available cannot be enabled.
-
-See 2.3. for a description of the parameter struct.
-
-Parameters: address of a buffer to store/load the feature list from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           -EINVAL if a cpu feature that is not available is to be enabled.
-           -EBUSY if at least one VCPU has already been defined.
-           0 in case of success.
-
-2.5. ATTRIBUTE: KVM_S390_VM_CPU_MACHINE_SUBFUNC (r/o)
-
-Allows user space to retrieve available cpu subfunctions without any filtering
-done by a set IBC. These subfunctions are indicated to the guest VCPU via
-query or "test bit" subfunctions and used e.g. by cpacf functions, plo and ptff.
-
-A subfunction block is only valid if KVM_S390_VM_CPU_MACHINE contains the
-STFL(E) bit introducing the affected instruction. If the affected instruction
-indicates subfunctions via a "query subfunction", the response block is
-contained in the returned struct. If the affected instruction
-indicates subfunctions via a "test bit" mechanism, the subfunction codes are
-contained in the returned struct in MSB 0 bit numbering.
-
-struct kvm_s390_vm_cpu_subfunc {
-       u8 plo[32];           # always valid (ESA/390 feature)
-       u8 ptff[16];          # valid with TOD-clock steering
-       u8 kmac[16];          # valid with Message-Security-Assist
-       u8 kmc[16];           # valid with Message-Security-Assist
-       u8 km[16];            # valid with Message-Security-Assist
-       u8 kimd[16];          # valid with Message-Security-Assist
-       u8 klmd[16];          # valid with Message-Security-Assist
-       u8 pckmo[16];         # valid with Message-Security-Assist-Extension 3
-       u8 kmctr[16];         # valid with Message-Security-Assist-Extension 4
-       u8 kmf[16];           # valid with Message-Security-Assist-Extension 4
-       u8 kmo[16];           # valid with Message-Security-Assist-Extension 4
-       u8 pcc[16];           # valid with Message-Security-Assist-Extension 4
-       u8 ppno[16];          # valid with Message-Security-Assist-Extension 5
-       u8 kma[16];           # valid with Message-Security-Assist-Extension 8
-       u8 kdsa[16];          # valid with Message-Security-Assist-Extension 9
-       u8 reserved[1792];    # reserved for future instructions
-};
-
-Parameters: address of a buffer to load the subfunction blocks from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           0 in case of success.
-
-2.6. ATTRIBUTE: KVM_S390_VM_CPU_PROCESSOR_SUBFUNC (r/w)
-
-Allows user space to retrieve or change cpu subfunctions to be indicated for
-all VCPUs of a VM. This attribute will only be available if kernel and
-hardware support are in place.
-
-The kernel uses the configured subfunction blocks for indication to
-the guest. A subfunction block will only be used if the associated STFL(E) bit
-has not been disabled by user space (so the instruction to be queried is
-actually available for the guest).
-
-As long as no data has been written, a read will fail. The IBC will be used
-to determine available subfunctions in this case, this will guarantee backward
-compatibility.
-
-See 2.5. for a description of the parameter struct.
-
-Parameters: address of a buffer to store/load the subfunction blocks from.
-Returns:    -EFAULT if the given address is not accessible from kernel space.
-           -EINVAL when reading, if there was no write yet.
-           -EBUSY if at least one VCPU has already been defined.
-           0 in case of success.
-
-3. GROUP: KVM_S390_VM_TOD
-Architectures: s390
-
-3.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH
-
-Allows user space to set/get the TOD clock extension (u8) (superseded by
-KVM_S390_VM_TOD_EXT).
-
-Parameters: address of a buffer in user space to store the data (u8) to
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           -EINVAL if setting the TOD clock extension to != 0 is not supported
-
-3.2. ATTRIBUTE: KVM_S390_VM_TOD_LOW
-
-Allows user space to set/get bits 0-63 of the TOD clock register as defined in
-the POP (u64).
-
-Parameters: address of a buffer in user space to store the data (u64) to
-Returns:    -EFAULT if the given address is not accessible from kernel space
-
-3.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
-Allows user space to set/get bits 0-63 of the TOD clock register as defined in
-the POP (u64). If the guest CPU model supports the TOD clock extension (u8), it
-also allows user space to get/set it. If the guest CPU model does not support
-it, it is stored as 0 and not allowed to be set to a value != 0.
-
-Parameters: address of a buffer in user space to store the data
-            (kvm_s390_vm_tod_clock) to
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           -EINVAL if setting the TOD clock extension to != 0 is not supported
-
-4. GROUP: KVM_S390_VM_CRYPTO
-Architectures: s390
-
-4.1. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_AES_KW (w/o)
-
-Allows user space to enable aes key wrapping, including generating a new
-wrapping key.
-
-Parameters: none
-Returns:    0
-
-4.2. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_DEA_KW (w/o)
-
-Allows user space to enable dea key wrapping, including generating a new
-wrapping key.
-
-Parameters: none
-Returns:    0
-
-4.3. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_AES_KW (w/o)
-
-Allows user space to disable aes key wrapping, clearing the wrapping key.
-
-Parameters: none
-Returns:    0
-
-4.4. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_DEA_KW (w/o)
-
-Allows user space to disable dea key wrapping, clearing the wrapping key.
-
-Parameters: none
-Returns:    0
-
-5. GROUP: KVM_S390_VM_MIGRATION
-Architectures: s390
-
-5.1. ATTRIBUTE: KVM_S390_VM_MIGRATION_STOP (w/o)
-
-Allows userspace to stop migration mode, needed for PGSTE migration.
-Setting this attribute when migration mode is not active will have no
-effects.
-
-Parameters: none
-Returns:    0
-
-5.2. ATTRIBUTE: KVM_S390_VM_MIGRATION_START (w/o)
-
-Allows userspace to start migration mode, needed for PGSTE migration.
-Setting this attribute when migration mode is already active will have
-no effects.
-
-Parameters: none
-Returns:    -ENOMEM if there is not enough free memory to start migration mode
-           -EINVAL if the state of the VM is invalid (e.g. no memory defined)
-           0 in case of success.
-
-5.3. ATTRIBUTE: KVM_S390_VM_MIGRATION_STATUS (r/o)
-
-Allows userspace to query the status of migration mode.
-
-Parameters: address of a buffer in user space to store the data (u64) to;
-           the data itself is either 0 if migration mode is disabled or 1
-           if it is enabled
-Returns:    -EFAULT if the given address is not accessible from kernel space
-           0 in case of success.
diff --git a/Documentation/virtual/kvm/devices/xics.txt b/Documentation/virtual/kvm/devices/xics.txt
deleted file mode 100644 (file)
index 4286493..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-XICS interrupt controller
-
-Device type supported: KVM_DEV_TYPE_XICS
-
-Groups:
-  KVM_DEV_XICS_SOURCES
-  Attributes: One per interrupt source, indexed by the source number.
-
-This device emulates the XICS (eXternal Interrupt Controller
-Specification) defined in PAPR.  The XICS has a set of interrupt
-sources, each identified by a 20-bit source number, and a set of
-Interrupt Control Presentation (ICP) entities, also called "servers",
-each associated with a virtual CPU.
-
-The ICP entities are created by enabling the KVM_CAP_IRQ_ARCH
-capability for each vcpu, specifying KVM_CAP_IRQ_XICS in args[0] and
-the interrupt server number (i.e. the vcpu number from the XICS's
-point of view) in args[1] of the kvm_enable_cap struct.  Each ICP has
-64 bits of state which can be read and written using the
-KVM_GET_ONE_REG and KVM_SET_ONE_REG ioctls on the vcpu.  The 64 bit
-state word has the following bitfields, starting at the
-least-significant end of the word:
-
-* Unused, 16 bits
-
-* Pending interrupt priority, 8 bits
-  Zero is the highest priority, 255 means no interrupt is pending.
-
-* Pending IPI (inter-processor interrupt) priority, 8 bits
-  Zero is the highest priority, 255 means no IPI is pending.
-
-* Pending interrupt source number, 24 bits
-  Zero means no interrupt pending, 2 means an IPI is pending
-
-* Current processor priority, 8 bits
-  Zero is the highest priority, meaning no interrupts can be
-  delivered, and 255 is the lowest priority.
-
-Each source has 64 bits of state that can be read and written using
-the KVM_GET_DEVICE_ATTR and KVM_SET_DEVICE_ATTR ioctls, specifying the
-KVM_DEV_XICS_SOURCES attribute group, with the attribute number being
-the interrupt source number.  The 64 bit state word has the following
-bitfields, starting from the least-significant end of the word:
-
-* Destination (server number), 32 bits
-  This specifies where the interrupt should be sent, and is the
-  interrupt server number specified for the destination vcpu.
-
-* Priority, 8 bits
-  This is the priority specified for this interrupt source, where 0 is
-  the highest priority and 255 is the lowest.  An interrupt with a
-  priority of 255 will never be delivered.
-
-* Level sensitive flag, 1 bit
-  This bit is 1 for a level-sensitive interrupt source, or 0 for
-  edge-sensitive (or MSI).
-
-* Masked flag, 1 bit
-  This bit is set to 1 if the interrupt is masked (cannot be delivered
-  regardless of its priority), for example by the ibm,int-off RTAS
-  call, or 0 if it is not masked.
-
-* Pending flag, 1 bit
-  This bit is 1 if the source has a pending interrupt, otherwise 0.
-
-Only one XICS instance may be created per VM.
diff --git a/Documentation/virtual/kvm/devices/xive.txt b/Documentation/virtual/kvm/devices/xive.txt
deleted file mode 100644 (file)
index 9a24a45..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-POWER9 eXternal Interrupt Virtualization Engine (XIVE Gen1)
-==========================================================
-
-Device types supported:
-  KVM_DEV_TYPE_XIVE     POWER9 XIVE Interrupt Controller generation 1
-
-This device acts as a VM interrupt controller. It provides the KVM
-interface to configure the interrupt sources of a VM in the underlying
-POWER9 XIVE interrupt controller.
-
-Only one XIVE instance may be instantiated. A guest XIVE device
-requires a POWER9 host and the guest OS should have support for the
-XIVE native exploitation interrupt mode. If not, it should run using
-the legacy interrupt mode, referred as XICS (POWER7/8).
-
-* Device Mappings
-
-  The KVM device exposes different MMIO ranges of the XIVE HW which
-  are required for interrupt management. These are exposed to the
-  guest in VMAs populated with a custom VM fault handler.
-
-  1. Thread Interrupt Management Area (TIMA)
-
-  Each thread has an associated Thread Interrupt Management context
-  composed of a set of registers. These registers let the thread
-  handle priority management and interrupt acknowledgment. The most
-  important are :
-
-      - Interrupt Pending Buffer     (IPB)
-      - Current Processor Priority   (CPPR)
-      - Notification Source Register (NSR)
-
-  They are exposed to software in four different pages each proposing
-  a view with a different privilege. The first page is for the
-  physical thread context and the second for the hypervisor. Only the
-  third (operating system) and the fourth (user level) are exposed the
-  guest.
-
-  2. Event State Buffer (ESB)
-
-  Each source is associated with an Event State Buffer (ESB) with
-  either a pair of even/odd pair of pages which provides commands to
-  manage the source: to trigger, to EOI, to turn off the source for
-  instance.
-
-  3. Device pass-through
-
-  When a device is passed-through into the guest, the source
-  interrupts are from a different HW controller (PHB4) and the ESB
-  pages exposed to the guest should accommadate this change.
-
-  The passthru_irq helpers, kvmppc_xive_set_mapped() and
-  kvmppc_xive_clr_mapped() are called when the device HW irqs are
-  mapped into or unmapped from the guest IRQ number space. The KVM
-  device extends these helpers to clear the ESB pages of the guest IRQ
-  number being mapped and then lets the VM fault handler repopulate.
-  The handler will insert the ESB page corresponding to the HW
-  interrupt of the device being passed-through or the initial IPI ESB
-  page if the device has being removed.
-
-  The ESB remapping is fully transparent to the guest and the OS
-  device driver. All handling is done within VFIO and the above
-  helpers in KVM-PPC.
-
-* Groups:
-
-  1. KVM_DEV_XIVE_GRP_CTRL
-  Provides global controls on the device
-  Attributes:
-    1.1 KVM_DEV_XIVE_RESET (write only)
-    Resets the interrupt controller configuration for sources and event
-    queues. To be used by kexec and kdump.
-    Errors: none
-
-    1.2 KVM_DEV_XIVE_EQ_SYNC (write only)
-    Sync all the sources and queues and mark the EQ pages dirty. This
-    to make sure that a consistent memory state is captured when
-    migrating the VM.
-    Errors: none
-
-  2. KVM_DEV_XIVE_GRP_SOURCE (write only)
-  Initializes a new source in the XIVE device and mask it.
-  Attributes:
-    Interrupt source number  (64-bit)
-  The kvm_device_attr.addr points to a __u64 value:
-  bits:     | 63   ....  2 |   1   |   0
-  values:   |    unused    | level | type
-  - type:  0:MSI 1:LSI
-  - level: assertion level in case of an LSI.
-  Errors:
-    -E2BIG:  Interrupt source number is out of range
-    -ENOMEM: Could not create a new source block
-    -EFAULT: Invalid user pointer for attr->addr.
-    -ENXIO:  Could not allocate underlying HW interrupt
-
-  3. KVM_DEV_XIVE_GRP_SOURCE_CONFIG (write only)
-  Configures source targeting
-  Attributes:
-    Interrupt source number  (64-bit)
-  The kvm_device_attr.addr points to a __u64 value:
-  bits:     | 63   ....  33 |  32  | 31 .. 3 |  2 .. 0
-  values:   |    eisn       | mask |  server | priority
-  - priority: 0-7 interrupt priority level
-  - server: CPU number chosen to handle the interrupt
-  - mask: mask flag (unused)
-  - eisn: Effective Interrupt Source Number
-  Errors:
-    -ENOENT: Unknown source number
-    -EINVAL: Not initialized source number
-    -EINVAL: Invalid priority
-    -EINVAL: Invalid CPU number.
-    -EFAULT: Invalid user pointer for attr->addr.
-    -ENXIO:  CPU event queues not configured or configuration of the
-             underlying HW interrupt failed
-    -EBUSY:  No CPU available to serve interrupt
-
-  4. KVM_DEV_XIVE_GRP_EQ_CONFIG (read-write)
-  Configures an event queue of a CPU
-  Attributes:
-    EQ descriptor identifier (64-bit)
-  The EQ descriptor identifier is a tuple (server, priority) :
-  bits:     | 63   ....  32 | 31 .. 3 |  2 .. 0
-  values:   |    unused     |  server | priority
-  The kvm_device_attr.addr points to :
-    struct kvm_ppc_xive_eq {
-       __u32 flags;
-       __u32 qshift;
-       __u64 qaddr;
-       __u32 qtoggle;
-       __u32 qindex;
-       __u8  pad[40];
-    };
-  - flags: queue flags
-    KVM_XIVE_EQ_ALWAYS_NOTIFY (required)
-       forces notification without using the coalescing mechanism
-       provided by the XIVE END ESBs.
-  - qshift: queue size (power of 2)
-  - qaddr: real address of queue
-  - qtoggle: current queue toggle bit
-  - qindex: current queue index
-  - pad: reserved for future use
-  Errors:
-    -ENOENT: Invalid CPU number
-    -EINVAL: Invalid priority
-    -EINVAL: Invalid flags
-    -EINVAL: Invalid queue size
-    -EINVAL: Invalid queue address
-    -EFAULT: Invalid user pointer for attr->addr.
-    -EIO:    Configuration of the underlying HW failed
-
-  5. KVM_DEV_XIVE_GRP_SOURCE_SYNC (write only)
-  Synchronize the source to flush event notifications
-  Attributes:
-    Interrupt source number  (64-bit)
-  Errors:
-    -ENOENT: Unknown source number
-    -EINVAL: Not initialized source number
-
-* VCPU state
-
-  The XIVE IC maintains VP interrupt state in an internal structure
-  called the NVT. When a VP is not dispatched on a HW processor
-  thread, this structure can be updated by HW if the VP is the target
-  of an event notification.
-
-  It is important for migration to capture the cached IPB from the NVT
-  as it synthesizes the priorities of the pending interrupts. We
-  capture a bit more to report debug information.
-
-  KVM_REG_PPC_VP_STATE (2 * 64bits)
-  bits:     |  63  ....  32  |  31  ....  0  |
-  values:   |   TIMA word0   |   TIMA word1  |
-  bits:     | 127       ..........       64  |
-  values:   |            unused              |
-
-* Migration:
-
-  Saving the state of a VM using the XIVE native exploitation mode
-  should follow a specific sequence. When the VM is stopped :
-
-  1. Mask all sources (PQ=01) to stop the flow of events.
-
-  2. Sync the XIVE device with the KVM control KVM_DEV_XIVE_EQ_SYNC to
-  flush any in-flight event notification and to stabilize the EQs. At
-  this stage, the EQ pages are marked dirty to make sure they are
-  transferred in the migration sequence.
-
-  3. Capture the state of the source targeting, the EQs configuration
-  and the state of thread interrupt context registers.
-
-  Restore is similar :
-
-  1. Restore the EQ configuration. As targeting depends on it.
-  2. Restore targeting
-  3. Restore the thread interrupt contexts
-  4. Restore the source states
-  5. Let the vCPU run
diff --git a/Documentation/virtual/kvm/halt-polling.txt b/Documentation/virtual/kvm/halt-polling.txt
deleted file mode 100644 (file)
index 4f791b1..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-The KVM halt polling system
-===========================
-
-The KVM halt polling system provides a feature within KVM whereby the latency
-of a guest can, under some circumstances, be reduced by polling in the host
-for some time period after the guest has elected to no longer run by cedeing.
-That is, when a guest vcpu has ceded, or in the case of powerpc when all of the
-vcpus of a single vcore have ceded, the host kernel polls for wakeup conditions
-before giving up the cpu to the scheduler in order to let something else run.
-
-Polling provides a latency advantage in cases where the guest can be run again
-very quickly by at least saving us a trip through the scheduler, normally on
-the order of a few micro-seconds, although performance benefits are workload
-dependant. In the event that no wakeup source arrives during the polling
-interval or some other task on the runqueue is runnable the scheduler is
-invoked. Thus halt polling is especially useful on workloads with very short
-wakeup periods where the time spent halt polling is minimised and the time
-savings of not invoking the scheduler are distinguishable.
-
-The generic halt polling code is implemented in:
-
-       virt/kvm/kvm_main.c: kvm_vcpu_block()
-
-The powerpc kvm-hv specific case is implemented in:
-
-       arch/powerpc/kvm/book3s_hv.c: kvmppc_vcore_blocked()
-
-Halt Polling Interval
-=====================
-
-The maximum time for which to poll before invoking the scheduler, referred to
-as the halt polling interval, is increased and decreased based on the perceived
-effectiveness of the polling in an attempt to limit pointless polling.
-This value is stored in either the vcpu struct:
-
-       kvm_vcpu->halt_poll_ns
-
-or in the case of powerpc kvm-hv, in the vcore struct:
-
-       kvmppc_vcore->halt_poll_ns
-
-Thus this is a per vcpu (or vcore) value.
-
-During polling if a wakeup source is received within the halt polling interval,
-the interval is left unchanged. In the event that a wakeup source isn't
-received during the polling interval (and thus schedule is invoked) there are
-two options, either the polling interval and total block time[0] were less than
-the global max polling interval (see module params below), or the total block
-time was greater than the global max polling interval.
-
-In the event that both the polling interval and total block time were less than
-the global max polling interval then the polling interval can be increased in
-the hope that next time during the longer polling interval the wake up source
-will be received while the host is polling and the latency benefits will be
-received. The polling interval is grown in the function grow_halt_poll_ns() and
-is multiplied by the module parameters halt_poll_ns_grow and
-halt_poll_ns_grow_start.
-
-In the event that the total block time was greater than the global max polling
-interval then the host will never poll for long enough (limited by the global
-max) to wakeup during the polling interval so it may as well be shrunk in order
-to avoid pointless polling. The polling interval is shrunk in the function
-shrink_halt_poll_ns() and is divided by the module parameter
-halt_poll_ns_shrink, or set to 0 iff halt_poll_ns_shrink == 0.
-
-It is worth noting that this adjustment process attempts to hone in on some
-steady state polling interval but will only really do a good job for wakeups
-which come at an approximately constant rate, otherwise there will be constant
-adjustment of the polling interval.
-
-[0] total block time: the time between when the halt polling function is
-                     invoked and a wakeup source received (irrespective of
-                     whether the scheduler is invoked within that function).
-
-Module Parameters
-=================
-
-The kvm module has 3 tuneable module parameters to adjust the global max
-polling interval as well as the rate at which the polling interval is grown and
-shrunk. These variables are defined in include/linux/kvm_host.h and as module
-parameters in virt/kvm/kvm_main.c, or arch/powerpc/kvm/book3s_hv.c in the
-powerpc kvm-hv case.
-
-Module Parameter       |   Description             |        Default Value
---------------------------------------------------------------------------------
-halt_poll_ns           | The global max polling    | KVM_HALT_POLL_NS_DEFAULT
-                       | interval which defines    |
-                       | the ceiling value of the  |
-                       | polling interval for      | (per arch value)
-                       | each vcpu.                |
---------------------------------------------------------------------------------
-halt_poll_ns_grow      | The value by which the    | 2
-                       | halt polling interval is  |
-                       | multiplied in the         |
-                       | grow_halt_poll_ns()       |
-                       | function.                 |
---------------------------------------------------------------------------------
-halt_poll_ns_grow_start | The initial value to grow | 10000
-                       | to from zero in the       |
-                       | grow_halt_poll_ns()       |
-                       | function.                 |
---------------------------------------------------------------------------------
-halt_poll_ns_shrink    | The value by which the    | 0
-                       | halt polling interval is  |
-                       | divided in the            |
-                       | shrink_halt_poll_ns()     |
-                       | function.                 |
---------------------------------------------------------------------------------
-
-These module parameters can be set from the debugfs files in:
-
-       /sys/module/kvm/parameters/
-
-Note: that these module parameters are system wide values and are not able to
-      be tuned on a per vm basis.
-
-Further Notes
-=============
-
-- Care should be taken when setting the halt_poll_ns module parameter as a
-large value has the potential to drive the cpu usage to 100% on a machine which
-would be almost entirely idle otherwise. This is because even if a guest has
-wakeups during which very little work is done and which are quite far apart, if
-the period is shorter than the global max polling interval (halt_poll_ns) then
-the host will always poll for the entire block time and thus cpu utilisation
-will go to 100%.
-
-- Halt polling essentially presents a trade off between power usage and latency
-and the module parameters should be used to tune the affinity for this. Idle
-cpu time is essentially converted to host kernel time with the aim of decreasing
-latency when entering the guest.
-
-- Halt polling will only be conducted by the host when no other tasks are
-runnable on that cpu, otherwise the polling will cease immediately and
-schedule will be invoked to allow that other task to run. Thus this doesn't
-allow a guest to denial of service the cpu.
diff --git a/Documentation/virtual/kvm/hypercalls.txt b/Documentation/virtual/kvm/hypercalls.txt
deleted file mode 100644 (file)
index da21065..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-Linux KVM Hypercall:
-===================
-X86:
- KVM Hypercalls have a three-byte sequence of either the vmcall or the vmmcall
- instruction. The hypervisor can replace it with instructions that are
- guaranteed to be supported.
-
- Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
- The hypercall number should be placed in rax and the return value will be
- placed in rax.  No other registers will be clobbered unless explicitly stated
- by the particular hypercall.
-
-S390:
-  R2-R7 are used for parameters 1-6. In addition, R1 is used for hypercall
-  number. The return value is written to R2.
-
-  S390 uses diagnose instruction as hypercall (0x500) along with hypercall
-  number in R1.
-
-  For further information on the S390 diagnose call as supported by KVM,
-  refer to Documentation/virtual/kvm/s390-diag.txt.
-
- PowerPC:
-  It uses R3-R10 and hypercall number in R11. R4-R11 are used as output registers.
-  Return value is placed in R3.
-
-  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
-
-MIPS:
-  KVM hypercalls use the HYPCALL instruction with code 0 and the hypercall
-  number in $2 (v0). Up to four arguments may be placed in $4-$7 (a0-a3) and
-  the return value is placed in $2 (v0).
-
-KVM Hypercalls Documentation
-===========================
-The template for each hypercall is:
-1. Hypercall name.
-2. Architecture(s)
-3. Status (deprecated, obsolete, active)
-4. Purpose
-
-1. KVM_HC_VAPIC_POLL_IRQ
-------------------------
-Architecture: x86
-Status: active
-Purpose: Trigger guest exit so that the host can check for pending
-interrupts on reentry.
-
-2. KVM_HC_MMU_OP
-------------------------
-Architecture: x86
-Status: deprecated.
-Purpose: Support MMU operations such as writing to PTE,
-flushing TLB, release PT.
-
-3. KVM_HC_FEATURES
-------------------------
-Architecture: PPC
-Status: active
-Purpose: Expose hypercall availability to the guest. On x86 platforms, cpuid
-used to enumerate which hypercalls are available. On PPC, either device tree
-based lookup ( which is also what EPAPR dictates) OR KVM specific enumeration
-mechanism (which is this hypercall) can be used.
-
-4. KVM_HC_PPC_MAP_MAGIC_PAGE
-------------------------
-Architecture: PPC
-Status: active
-Purpose: To enable communication between the hypervisor and guest there is a
-shared page that contains parts of supervisor visible register state.
-The guest can map this shared page to access its supervisor register through
-memory using this hypercall.
-
-5. KVM_HC_KICK_CPU
-------------------------
-Architecture: x86
-Status: active
-Purpose: Hypercall used to wakeup a vcpu from HLT state
-Usage example : A vcpu of a paravirtualized guest that is busywaiting in guest
-kernel mode for an event to occur (ex: a spinlock to become available) can
-execute HLT instruction once it has busy-waited for more than a threshold
-time-interval. Execution of HLT instruction would cause the hypervisor to put
-the vcpu to sleep until occurrence of an appropriate event. Another vcpu of the
-same guest can wakeup the sleeping vcpu by issuing KVM_HC_KICK_CPU hypercall,
-specifying APIC ID (a1) of the vcpu to be woken up. An additional argument (a0)
-is used in the hypercall for future use.
-
-
-6. KVM_HC_CLOCK_PAIRING
-------------------------
-Architecture: x86
-Status: active
-Purpose: Hypercall used to synchronize host and guest clocks.
-Usage:
-
-a0: guest physical address where host copies
-"struct kvm_clock_offset" structure.
-
-a1: clock_type, ATM only KVM_CLOCK_PAIRING_WALLCLOCK (0)
-is supported (corresponding to the host's CLOCK_REALTIME clock).
-
-               struct kvm_clock_pairing {
-                       __s64 sec;
-                       __s64 nsec;
-                       __u64 tsc;
-                       __u32 flags;
-                       __u32 pad[9];
-               };
-
-       Where:
-               * sec: seconds from clock_type clock.
-               * nsec: nanoseconds from clock_type clock.
-               * tsc: guest TSC value used to calculate sec/nsec pair
-               * flags: flags, unused (0) at the moment.
-
-The hypercall lets a guest compute a precise timestamp across
-host and guest.  The guest can use the returned TSC value to
-compute the CLOCK_REALTIME for its clock, at the same instant.
-
-Returns KVM_EOPNOTSUPP if the host does not use TSC clocksource,
-or if clock type is different than KVM_CLOCK_PAIRING_WALLCLOCK.
-
-6. KVM_HC_SEND_IPI
-------------------------
-Architecture: x86
-Status: active
-Purpose: Send IPIs to multiple vCPUs.
-
-a0: lower part of the bitmap of destination APIC IDs
-a1: higher part of the bitmap of destination APIC IDs
-a2: the lowest APIC ID in bitmap
-a3: APIC ICR
-
-The hypercall lets a guest send multicast IPIs, with at most 128
-128 destinations per hypercall in 64-bit mode and 64 vCPUs per
-hypercall in 32-bit mode.  The destinations are represented by a
-bitmap contained in the first two arguments (a0 and a1). Bit 0 of
-a0 corresponds to the APIC ID in the third argument (a2), bit 1
-corresponds to the APIC ID a2+1, and so on.
-
-Returns the number of CPUs to which the IPIs were delivered successfully.
-
-7. KVM_HC_SCHED_YIELD
-------------------------
-Architecture: x86
-Status: active
-Purpose: Hypercall used to yield if the IPI target vCPU is preempted
-
-a0: destination APIC ID
-
-Usage example: When sending a call-function IPI-many to vCPUs, yield if
-any of the IPI target vCPUs was preempted.
diff --git a/Documentation/virtual/kvm/index.rst b/Documentation/virtual/kvm/index.rst
deleted file mode 100644 (file)
index 0b206a0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===
-KVM
-===
-
-.. toctree::
-   :maxdepth: 2
-
-   amd-memory-encryption
-   cpuid
diff --git a/Documentation/virtual/kvm/locking.txt b/Documentation/virtual/kvm/locking.txt
deleted file mode 100644 (file)
index 635cd6e..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-KVM Lock Overview
-=================
-
-1. Acquisition Orders
----------------------
-
-The acquisition orders for mutexes are as follows:
-
-- kvm->lock is taken outside vcpu->mutex
-
-- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock
-
-- kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
-  them together is quite rare.
-
-On x86, vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock.
-
-Everything else is a leaf: no other lock is taken inside the critical
-sections.
-
-2: Exception
-------------
-
-Fast page fault:
-
-Fast page fault is the fast path which fixes the guest page fault out of
-the mmu-lock on x86. Currently, the page fault can be fast in one of the
-following two cases:
-
-1. Access Tracking: The SPTE is not present, but it is marked for access
-tracking i.e. the SPTE_SPECIAL_MASK is set. That means we need to
-restore the saved R/X bits. This is described in more detail later below.
-
-2. Write-Protection: The SPTE is present and the fault is
-caused by write-protect. That means we just need to change the W bit of the 
-spte.
-
-What we use to avoid all the race is the SPTE_HOST_WRITEABLE bit and
-SPTE_MMU_WRITEABLE bit on the spte:
-- SPTE_HOST_WRITEABLE means the gfn is writable on host.
-- SPTE_MMU_WRITEABLE means the gfn is writable on mmu. The bit is set when
-  the gfn is writable on guest mmu and it is not write-protected by shadow
-  page write-protection.
-
-On fast page fault path, we will use cmpxchg to atomically set the spte W
-bit if spte.SPTE_HOST_WRITEABLE = 1 and spte.SPTE_WRITE_PROTECT = 1, or 
-restore the saved R/X bits if VMX_EPT_TRACK_ACCESS mask is set, or both. This
-is safe because whenever changing these bits can be detected by cmpxchg.
-
-But we need carefully check these cases:
-1): The mapping from gfn to pfn
-The mapping from gfn to pfn may be changed since we can only ensure the pfn
-is not changed during cmpxchg. This is a ABA problem, for example, below case
-will happen:
-
-At the beginning:
-gpte = gfn1
-gfn1 is mapped to pfn1 on host
-spte is the shadow page table entry corresponding with gpte and
-spte = pfn1
-
-   VCPU 0                           VCPU0
-on fast page fault path:
-
-   old_spte = *spte;
-                                 pfn1 is swapped out:
-                                    spte = 0;
-
-                                 pfn1 is re-alloced for gfn2.
-
-                                 gpte is changed to point to
-                                 gfn2 by the guest:
-                                    spte = pfn1;
-
-   if (cmpxchg(spte, old_spte, old_spte+W)
-       mark_page_dirty(vcpu->kvm, gfn1)
-             OOPS!!!
-
-We dirty-log for gfn1, that means gfn2 is lost in dirty-bitmap.
-
-For direct sp, we can easily avoid it since the spte of direct sp is fixed
-to gfn. For indirect sp, before we do cmpxchg, we call gfn_to_pfn_atomic()
-to pin gfn to pfn, because after gfn_to_pfn_atomic():
-- We have held the refcount of pfn that means the pfn can not be freed and
-  be reused for another gfn.
-- The pfn is writable that means it can not be shared between different gfns
-  by KSM.
-
-Then, we can ensure the dirty bitmaps is correctly set for a gfn.
-
-Currently, to simplify the whole things, we disable fast page fault for
-indirect shadow page.
-
-2): Dirty bit tracking
-In the origin code, the spte can be fast updated (non-atomically) if the
-spte is read-only and the Accessed bit has already been set since the
-Accessed bit and Dirty bit can not be lost.
-
-But it is not true after fast page fault since the spte can be marked
-writable between reading spte and updating spte. Like below case:
-
-At the beginning:
-spte.W = 0
-spte.Accessed = 1
-
-   VCPU 0                                       VCPU0
-In mmu_spte_clear_track_bits():
-
-   old_spte = *spte;
-
-   /* 'if' condition is satisfied. */
-   if (old_spte.Accessed == 1 &&
-        old_spte.W == 0)
-      spte = 0ull;
-                                         on fast page fault path:
-                                             spte.W = 1
-                                         memory write on the spte:
-                                             spte.Dirty = 1
-
-
-   else
-      old_spte = xchg(spte, 0ull)
-
-
-   if (old_spte.Accessed == 1)
-      kvm_set_pfn_accessed(spte.pfn);
-   if (old_spte.Dirty == 1)
-      kvm_set_pfn_dirty(spte.pfn);
-      OOPS!!!
-
-The Dirty bit is lost in this case.
-
-In order to avoid this kind of issue, we always treat the spte as "volatile"
-if it can be updated out of mmu-lock, see spte_has_volatile_bits(), it means,
-the spte is always atomically updated in this case.
-
-3): flush tlbs due to spte updated
-If the spte is updated from writable to readonly, we should flush all TLBs,
-otherwise rmap_write_protect will find a read-only spte, even though the
-writable spte might be cached on a CPU's TLB.
-
-As mentioned before, the spte can be updated to writable out of mmu-lock on
-fast page fault path, in order to easily audit the path, we see if TLBs need
-be flushed caused by this reason in mmu_spte_update() since this is a common
-function to update spte (present -> present).
-
-Since the spte is "volatile" if it can be updated out of mmu-lock, we always
-atomically update the spte, the race caused by fast page fault can be avoided,
-See the comments in spte_has_volatile_bits() and mmu_spte_update().
-
-Lockless Access Tracking:
-
-This is used for Intel CPUs that are using EPT but do not support the EPT A/D
-bits. In this case, when the KVM MMU notifier is called to track accesses to a
-page (via kvm_mmu_notifier_clear_flush_young), it marks the PTE as not-present
-by clearing the RWX bits in the PTE and storing the original R & X bits in
-some unused/ignored bits. In addition, the SPTE_SPECIAL_MASK is also set on the
-PTE (using the ignored bit 62). When the VM tries to access the page later on,
-a fault is generated and the fast page fault mechanism described above is used
-to atomically restore the PTE to a Present state. The W bit is not saved when
-the PTE is marked for access tracking and during restoration to the Present
-state, the W bit is set depending on whether or not it was a write access. If
-it wasn't, then the W bit will remain clear until a write access happens, at 
-which time it will be set using the Dirty tracking mechanism described above.
-
-3. Reference
-------------
-
-Name:          kvm_lock
-Type:          mutex
-Arch:          any
-Protects:      - vm_list
-
-Name:          kvm_count_lock
-Type:          raw_spinlock_t
-Arch:          any
-Protects:      - hardware virtualization enable/disable
-Comment:       'raw' because hardware enabling/disabling must be atomic /wrt
-               migration.
-
-Name:          kvm_arch::tsc_write_lock
-Type:          raw_spinlock
-Arch:          x86
-Protects:      - kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
-               - tsc offset in vmcb
-Comment:       'raw' because updating the tsc offsets must not be preempted.
-
-Name:          kvm->mmu_lock
-Type:          spinlock_t
-Arch:          any
-Protects:      -shadow page/shadow tlb entry
-Comment:       it is a spinlock since it is used in mmu notifier.
-
-Name:          kvm->srcu
-Type:          srcu lock
-Arch:          any
-Protects:      - kvm->memslots
-               - kvm->buses
-Comment:       The srcu read lock must be held while accessing memslots (e.g.
-               when using gfn_to_* functions) and while accessing in-kernel
-               MMIO/PIO address->device structure mapping (kvm->buses).
-               The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
-               if it is needed by multiple functions.
-
-Name:          blocked_vcpu_on_cpu_lock
-Type:          spinlock_t
-Arch:          x86
-Protects:      blocked_vcpu_on_cpu
-Comment:       This is a per-CPU lock and it is used for VT-d posted-interrupts.
-               When VT-d posted-interrupts is supported and the VM has assigned
-               devices, we put the blocked vCPU on the list blocked_vcpu_on_cpu
-               protected by blocked_vcpu_on_cpu_lock, when VT-d hardware issues
-               wakeup notification event since external interrupts from the
-               assigned devices happens, we will find the vCPU on the list to
-               wakeup.
diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt
deleted file mode 100644 (file)
index 2efe0ef..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-The x86 kvm shadow mmu
-======================
-
-The mmu (in arch/x86/kvm, files mmu.[ch] and paging_tmpl.h) is responsible
-for presenting a standard x86 mmu to the guest, while translating guest
-physical addresses to host physical addresses.
-
-The mmu code attempts to satisfy the following requirements:
-
-- correctness: the guest should not be able to determine that it is running
-               on an emulated mmu except for timing (we attempt to comply
-               with the specification, not emulate the characteristics of
-               a particular implementation such as tlb size)
-- security:    the guest must not be able to touch host memory not assigned
-               to it
-- performance: minimize the performance penalty imposed by the mmu
-- scaling:     need to scale to large memory and large vcpu guests
-- hardware:    support the full range of x86 virtualization hardware
-- integration: Linux memory management code must be in control of guest memory
-               so that swapping, page migration, page merging, transparent
-               hugepages, and similar features work without change
-- dirty tracking: report writes to guest memory to enable live migration
-               and framebuffer-based displays
-- footprint:   keep the amount of pinned kernel memory low (most memory
-               should be shrinkable)
-- reliability:  avoid multipage or GFP_ATOMIC allocations
-
-Acronyms
-========
-
-pfn   host page frame number
-hpa   host physical address
-hva   host virtual address
-gfn   guest frame number
-gpa   guest physical address
-gva   guest virtual address
-ngpa  nested guest physical address
-ngva  nested guest virtual address
-pte   page table entry (used also to refer generically to paging structure
-      entries)
-gpte  guest pte (referring to gfns)
-spte  shadow pte (referring to pfns)
-tdp   two dimensional paging (vendor neutral term for NPT and EPT)
-
-Virtual and real hardware supported
-===================================
-
-The mmu supports first-generation mmu hardware, which allows an atomic switch
-of the current paging mode and cr3 during guest entry, as well as
-two-dimensional paging (AMD's NPT and Intel's EPT).  The emulated hardware
-it exposes is the traditional 2/3/4 level x86 mmu, with support for global
-pages, pae, pse, pse36, cr0.wp, and 1GB pages. Emulated hardware also
-able to expose NPT capable hardware on NPT capable hosts.
-
-Translation
-===========
-
-The primary job of the mmu is to program the processor's mmu to translate
-addresses for the guest.  Different translations are required at different
-times:
-
-- when guest paging is disabled, we translate guest physical addresses to
-  host physical addresses (gpa->hpa)
-- when guest paging is enabled, we translate guest virtual addresses, to
-  guest physical addresses, to host physical addresses (gva->gpa->hpa)
-- when the guest launches a guest of its own, we translate nested guest
-  virtual addresses, to nested guest physical addresses, to guest physical
-  addresses, to host physical addresses (ngva->ngpa->gpa->hpa)
-
-The primary challenge is to encode between 1 and 3 translations into hardware
-that support only 1 (traditional) and 2 (tdp) translations.  When the
-number of required translations matches the hardware, the mmu operates in
-direct mode; otherwise it operates in shadow mode (see below).
-
-Memory
-======
-
-Guest memory (gpa) is part of the user address space of the process that is
-using kvm.  Userspace defines the translation between guest addresses and user
-addresses (gpa->hva); note that two gpas may alias to the same hva, but not
-vice versa.
-
-These hvas may be backed using any method available to the host: anonymous
-memory, file backed memory, and device memory.  Memory might be paged by the
-host at any time.
-
-Events
-======
-
-The mmu is driven by events, some from the guest, some from the host.
-
-Guest generated events:
-- writes to control registers (especially cr3)
-- invlpg/invlpga instruction execution
-- access to missing or protected translations
-
-Host generated events:
-- changes in the gpa->hpa translation (either through gpa->hva changes or
-  through hva->hpa changes)
-- memory pressure (the shrinker)
-
-Shadow pages
-============
-
-The principal data structure is the shadow page, 'struct kvm_mmu_page'.  A
-shadow page contains 512 sptes, which can be either leaf or nonleaf sptes.  A
-shadow page may contain a mix of leaf and nonleaf sptes.
-
-A nonleaf spte allows the hardware mmu to reach the leaf pages and
-is not related to a translation directly.  It points to other shadow pages.
-
-A leaf spte corresponds to either one or two translations encoded into
-one paging structure entry.  These are always the lowest level of the
-translation stack, with optional higher level translations left to NPT/EPT.
-Leaf ptes point at guest pages.
-
-The following table shows translations encoded by leaf ptes, with higher-level
-translations in parentheses:
-
- Non-nested guests:
-  nonpaging:     gpa->hpa
-  paging:        gva->gpa->hpa
-  paging, tdp:   (gva->)gpa->hpa
- Nested guests:
-  non-tdp:       ngva->gpa->hpa  (*)
-  tdp:           (ngva->)ngpa->gpa->hpa
-
-(*) the guest hypervisor will encode the ngva->gpa translation into its page
-    tables if npt is not present
-
-Shadow pages contain the following information:
-  role.level:
-    The level in the shadow paging hierarchy that this shadow page belongs to.
-    1=4k sptes, 2=2M sptes, 3=1G sptes, etc.
-  role.direct:
-    If set, leaf sptes reachable from this page are for a linear range.
-    Examples include real mode translation, large guest pages backed by small
-    host pages, and gpa->hpa translations when NPT or EPT is active.
-    The linear range starts at (gfn << PAGE_SHIFT) and its size is determined
-    by role.level (2MB for first level, 1GB for second level, 0.5TB for third
-    level, 256TB for fourth level)
-    If clear, this page corresponds to a guest page table denoted by the gfn
-    field.
-  role.quadrant:
-    When role.gpte_is_8_bytes=0, the guest uses 32-bit gptes while the host uses 64-bit
-    sptes.  That means a guest page table contains more ptes than the host,
-    so multiple shadow pages are needed to shadow one guest page.
-    For first-level shadow pages, role.quadrant can be 0 or 1 and denotes the
-    first or second 512-gpte block in the guest page table.  For second-level
-    page tables, each 32-bit gpte is converted to two 64-bit sptes
-    (since each first-level guest page is shadowed by two first-level
-    shadow pages) so role.quadrant takes values in the range 0..3.  Each
-    quadrant maps 1GB virtual address space.
-  role.access:
-    Inherited guest access permissions in the form uwx.  Note execute
-    permission is positive, not negative.
-  role.invalid:
-    The page is invalid and should not be used.  It is a root page that is
-    currently pinned (by a cpu hardware register pointing to it); once it is
-    unpinned it will be destroyed.
-  role.gpte_is_8_bytes:
-    Reflects the size of the guest PTE for which the page is valid, i.e. '1'
-    if 64-bit gptes are in use, '0' if 32-bit gptes are in use.
-  role.nxe:
-    Contains the value of efer.nxe for which the page is valid.
-  role.cr0_wp:
-    Contains the value of cr0.wp for which the page is valid.
-  role.smep_andnot_wp:
-    Contains the value of cr4.smep && !cr0.wp for which the page is valid
-    (pages for which this is true are different from other pages; see the
-    treatment of cr0.wp=0 below).
-  role.smap_andnot_wp:
-    Contains the value of cr4.smap && !cr0.wp for which the page is valid
-    (pages for which this is true are different from other pages; see the
-    treatment of cr0.wp=0 below).
-  role.ept_sp:
-    This is a virtual flag to denote a shadowed nested EPT page.  ept_sp
-    is true if "cr0_wp && smap_andnot_wp", an otherwise invalid combination.
-  role.smm:
-    Is 1 if the page is valid in system management mode.  This field
-    determines which of the kvm_memslots array was used to build this
-    shadow page; it is also used to go back from a struct kvm_mmu_page
-    to a memslot, through the kvm_memslots_for_spte_role macro and
-    __gfn_to_memslot.
-  role.ad_disabled:
-    Is 1 if the MMU instance cannot use A/D bits.  EPT did not have A/D
-    bits before Haswell; shadow EPT page tables also cannot use A/D bits
-    if the L1 hypervisor does not enable them.
-  gfn:
-    Either the guest page table containing the translations shadowed by this
-    page, or the base page frame for linear translations.  See role.direct.
-  spt:
-    A pageful of 64-bit sptes containing the translations for this page.
-    Accessed by both kvm and hardware.
-    The page pointed to by spt will have its page->private pointing back
-    at the shadow page structure.
-    sptes in spt point either at guest pages, or at lower-level shadow pages.
-    Specifically, if sp1 and sp2 are shadow pages, then sp1->spt[n] may point
-    at __pa(sp2->spt).  sp2 will point back at sp1 through parent_pte.
-    The spt array forms a DAG structure with the shadow page as a node, and
-    guest pages as leaves.
-  gfns:
-    An array of 512 guest frame numbers, one for each present pte.  Used to
-    perform a reverse map from a pte to a gfn. When role.direct is set, any
-    element of this array can be calculated from the gfn field when used, in
-    this case, the array of gfns is not allocated. See role.direct and gfn.
-  root_count:
-    A counter keeping track of how many hardware registers (guest cr3 or
-    pdptrs) are now pointing at the page.  While this counter is nonzero, the
-    page cannot be destroyed.  See role.invalid.
-  parent_ptes:
-    The reverse mapping for the pte/ptes pointing at this page's spt. If
-    parent_ptes bit 0 is zero, only one spte points at this page and
-    parent_ptes points at this single spte, otherwise, there exists multiple
-    sptes pointing at this page and (parent_ptes & ~0x1) points at a data
-    structure with a list of parent sptes.
-  unsync:
-    If true, then the translations in this page may not match the guest's
-    translation.  This is equivalent to the state of the tlb when a pte is
-    changed but before the tlb entry is flushed.  Accordingly, unsync ptes
-    are synchronized when the guest executes invlpg or flushes its tlb by
-    other means.  Valid for leaf pages.
-  unsync_children:
-    How many sptes in the page point at pages that are unsync (or have
-    unsynchronized children).
-  unsync_child_bitmap:
-    A bitmap indicating which sptes in spt point (directly or indirectly) at
-    pages that may be unsynchronized.  Used to quickly locate all unsychronized
-    pages reachable from a given page.
-  clear_spte_count:
-    Only present on 32-bit hosts, where a 64-bit spte cannot be written
-    atomically.  The reader uses this while running out of the MMU lock
-    to detect in-progress updates and retry them until the writer has
-    finished the write.
-  write_flooding_count:
-    A guest may write to a page table many times, causing a lot of
-    emulations if the page needs to be write-protected (see "Synchronized
-    and unsynchronized pages" below).  Leaf pages can be unsynchronized
-    so that they do not trigger frequent emulation, but this is not
-    possible for non-leafs.  This field counts the number of emulations
-    since the last time the page table was actually used; if emulation
-    is triggered too frequently on this page, KVM will unmap the page
-    to avoid emulation in the future.
-
-Reverse map
-===========
-
-The mmu maintains a reverse mapping whereby all ptes mapping a page can be
-reached given its gfn.  This is used, for example, when swapping out a page.
-
-Synchronized and unsynchronized pages
-=====================================
-
-The guest uses two events to synchronize its tlb and page tables: tlb flushes
-and page invalidations (invlpg).
-
-A tlb flush means that we need to synchronize all sptes reachable from the
-guest's cr3.  This is expensive, so we keep all guest page tables write
-protected, and synchronize sptes to gptes when a gpte is written.
-
-A special case is when a guest page table is reachable from the current
-guest cr3.  In this case, the guest is obliged to issue an invlpg instruction
-before using the translation.  We take advantage of that by removing write
-protection from the guest page, and allowing the guest to modify it freely.
-We synchronize modified gptes when the guest invokes invlpg.  This reduces
-the amount of emulation we have to do when the guest modifies multiple gptes,
-or when the a guest page is no longer used as a page table and is used for
-random guest data.
-
-As a side effect we have to resynchronize all reachable unsynchronized shadow
-pages on a tlb flush.
-
-
-Reaction to events
-==================
-
-- guest page fault (or npt page fault, or ept violation)
-
-This is the most complicated event.  The cause of a page fault can be:
-
-  - a true guest fault (the guest translation won't allow the access) (*)
-  - access to a missing translation
-  - access to a protected translation
-    - when logging dirty pages, memory is write protected
-    - synchronized shadow pages are write protected (*)
-  - access to untranslatable memory (mmio)
-
-  (*) not applicable in direct mode
-
-Handling a page fault is performed as follows:
-
- - if the RSV bit of the error code is set, the page fault is caused by guest
-   accessing MMIO and cached MMIO information is available.
-   - walk shadow page table
-   - check for valid generation number in the spte (see "Fast invalidation of
-     MMIO sptes" below)
-   - cache the information to vcpu->arch.mmio_gva, vcpu->arch.access and
-     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.
- - 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
- - determine the host page
-   - if this is an mmio request, there is no host page; cache the info to
-     vcpu->arch.mmio_gva, vcpu->arch.access and vcpu->arch.mmio_gfn
- - walk the shadow page table to find the spte for the translation,
-   instantiating missing intermediate page tables as necessary
-   - If this is an mmio request, cache the mmio info to the spte and set some
-     reserved bit on the spte (see callers of kvm_mmu_set_mmio_spte_mask)
- - try to unsynchronize the page
-   - if successful, we can let the guest continue and modify the gpte
- - emulate the instruction
-   - if failed, unshadow the page and let the guest continue
- - update any translations that were modified by the instruction
-
-invlpg handling:
-
-  - walk the shadow page hierarchy and drop affected translations
-  - try to reinstantiate the indicated translation in the hope that the
-    guest will use it in the near future
-
-Guest control register updates:
-
-- mov to cr3
-  - look up new shadow roots
-  - synchronize newly reachable shadow pages
-
-- mov to cr0/cr4/efer
-  - set up mmu context for new paging mode
-  - look up new shadow roots
-  - synchronize newly reachable shadow pages
-
-Host translation updates:
-
-  - mmu notifier called with updated hva
-  - look up affected sptes through reverse map
-  - drop (or update) translations
-
-Emulating cr0.wp
-================
-
-If tdp is not enabled, the host must keep cr0.wp=1 so page write protection
-works for the guest kernel, not guest guest userspace.  When the guest
-cr0.wp=1, this does not present a problem.  However when the guest cr0.wp=0,
-we cannot map the permissions for gpte.u=1, gpte.w=0 to any spte (the
-semantics require allowing any guest kernel access plus user read access).
-
-We handle this by mapping the permissions to two possible sptes, depending
-on fault type:
-
-- kernel write fault: spte.u=0, spte.w=1 (allows full kernel access,
-  disallows user access)
-- read fault: spte.u=1, spte.w=0 (allows full read access, disallows kernel
-  write access)
-
-(user write faults generate a #PF)
-
-In the first case there are two additional complications:
-- if CR4.SMEP is enabled: since we've turned the page into a kernel page,
-  the kernel may now execute it.  We handle this by also setting spte.nx.
-  If we get a user fetch or read fault, we'll change spte.u=1 and
-  spte.nx=gpte.nx back.  For this to work, KVM forces EFER.NX to 1 when
-  shadow paging is in use.
-- if CR4.SMAP is disabled: since the page has been changed to a kernel
-  page, it can not be reused when CR4.SMAP is enabled. We set
-  CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
-  here we do not care the case that CR4.SMAP is enabled since KVM will
-  directly inject #PF to guest due to failed permission check.
-
-To prevent an spte that was converted into a kernel page with cr0.wp=0
-from being written by the kernel after cr0.wp has changed to 1, we make
-the value of cr0.wp part of the page role.  This means that an spte created
-with one value of cr0.wp cannot be used when cr0.wp has a different value -
-it will simply be missed by the shadow page lookup code.  A similar issue
-exists when an spte created with cr0.wp=0 and cr4.smep=0 is used after
-changing cr4.smep to 1.  To avoid this, the value of !cr0.wp && cr4.smep
-is also made a part of the page role.
-
-Large pages
-===========
-
-The mmu supports all combinations of large and small guest and host pages.
-Supported page sizes include 4k, 2M, 4M, and 1G.  4M pages are treated as
-two separate 2M pages, on both guest and host, since the mmu always uses PAE
-paging.
-
-To instantiate a large spte, four constraints must be satisfied:
-
-- the spte must point to a large host page
-- the guest pte must be a large pte of at least equivalent size (if tdp is
-  enabled, there is no guest pte and this condition is satisfied)
-- if the spte will be writeable, the large page frame may not overlap any
-  write-protected pages
-- the guest page must be wholly contained by a single memory slot
-
-To check the last two conditions, the mmu maintains a ->disallow_lpage set of
-arrays for each memory slot and large page size.  Every write protected page
-causes its disallow_lpage to be incremented, thus preventing instantiation of
-a large spte.  The frames at the end of an unaligned memory slot have
-artificially inflated ->disallow_lpages so they can never be instantiated.
-
-Fast invalidation of MMIO sptes
-===============================
-
-As mentioned in "Reaction to events" above, kvm will cache MMIO
-information in leaf sptes.  When a new memslot is added or an existing
-memslot is changed, this information may become stale and needs to be
-invalidated.  This also needs to hold the MMU lock while walking all
-shadow pages, and is made more scalable with a similar technique.
-
-MMIO sptes have a few spare bits, which are used to store a
-generation number.  The global generation number is stored in
-kvm_memslots(kvm)->generation, and increased whenever guest memory info
-changes.
-
-When KVM finds an MMIO spte, it checks the generation number of the spte.
-If the generation number of the spte does not equal the global generation
-number, it will ignore the cached MMIO information and handle the page
-fault through the slow path.
-
-Since only 19 bits are used to store generation-number on mmio spte, all
-pages are zapped when there is an overflow.
-
-Unfortunately, a single memory access might access kvm_memslots(kvm) multiple
-times, the last one happening when the generation number is retrieved and
-stored into the MMIO spte.  Thus, the MMIO spte might be created based on
-out-of-date information, but with an up-to-date generation number.
-
-To avoid this, the generation number is incremented again after synchronize_srcu
-returns; thus, bit 63 of kvm_memslots(kvm)->generation set to 1 only during a
-memslot update, while some SRCU readers might be using the old copy.  We do not
-want to use an MMIO sptes created with an odd generation number, and we can do
-this without losing a bit in the MMIO spte.  The "update in-progress" bit of the
-generation is not stored in MMIO spte, and is so is implicitly zero when the
-generation is extracted out of the spte.  If KVM is unlucky and creates an MMIO
-spte while an update is in-progress, the next access to the spte will always be
-a cache miss.  For example, a subsequent access during the update window will
-miss due to the in-progress flag diverging, while an access after the update
-window closes will have a higher generation number (as compared to the spte).
-
-
-Further reading
-===============
-
-- NPT presentation from KVM Forum 2008
-  http://www.linux-kvm.org/images/c/c8/KvmForum2008%24kdf2008_21.pdf
-
diff --git a/Documentation/virtual/kvm/msr.txt b/Documentation/virtual/kvm/msr.txt
deleted file mode 100644 (file)
index df1f433..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-KVM-specific MSRs.
-Glauber Costa <glommer@redhat.com>, Red Hat Inc, 2010
-=====================================================
-
-KVM makes use of some custom MSRs to service some requests.
-
-Custom MSRs have a range reserved for them, that goes from
-0x4b564d00 to 0x4b564dff. There are MSRs outside this area,
-but they are deprecated and their use is discouraged.
-
-Custom MSR list
---------
-
-The current supported Custom MSR list is:
-
-MSR_KVM_WALL_CLOCK_NEW:   0x4b564d00
-
-       data: 4-byte alignment physical address of a memory area which must be
-       in guest RAM. This memory is expected to hold a copy of the following
-       structure:
-
-       struct pvclock_wall_clock {
-               u32   version;
-               u32   sec;
-               u32   nsec;
-       } __attribute__((__packed__));
-
-       whose data will be filled in by the hypervisor. The hypervisor is only
-       guaranteed to update this data at the moment of MSR write.
-       Users that want to reliably query this information more than once have
-       to write more than once to this MSR. Fields have the following meanings:
-
-               version: guest has to check version before and after grabbing
-               time information and check that they are both equal and even.
-               An odd version indicates an in-progress update.
-
-               sec: number of seconds for wallclock at time of boot.
-
-               nsec: number of nanoseconds for wallclock at time of boot.
-
-       In order to get the current wallclock time, the system_time from
-       MSR_KVM_SYSTEM_TIME_NEW needs to be added.
-
-       Note that although MSRs are per-CPU entities, the effect of this
-       particular MSR is global.
-
-       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
-       leaf prior to usage.
-
-MSR_KVM_SYSTEM_TIME_NEW:  0x4b564d01
-
-       data: 4-byte aligned physical address of a memory area which must be in
-       guest RAM, plus an enable bit in bit 0. This memory is expected to hold
-       a copy of the following structure:
-
-       struct pvclock_vcpu_time_info {
-               u32   version;
-               u32   pad0;
-               u64   tsc_timestamp;
-               u64   system_time;
-               u32   tsc_to_system_mul;
-               s8    tsc_shift;
-               u8    flags;
-               u8    pad[2];
-       } __attribute__((__packed__)); /* 32 bytes */
-
-       whose data will be filled in by the hypervisor periodically. Only one
-       write, or registration, is needed for each VCPU. The interval between
-       updates of this structure is arbitrary and implementation-dependent.
-       The hypervisor may update this structure at any time it sees fit until
-       anything with bit0 == 0 is written to it.
-
-       Fields have the following meanings:
-
-               version: guest has to check version before and after grabbing
-               time information and check that they are both equal and even.
-               An odd version indicates an in-progress update.
-
-               tsc_timestamp: the tsc value at the current VCPU at the time
-               of the update of this structure. Guests can subtract this value
-               from current tsc to derive a notion of elapsed time since the
-               structure update.
-
-               system_time: a host notion of monotonic time, including sleep
-               time at the time this structure was last updated. Unit is
-               nanoseconds.
-
-               tsc_to_system_mul: multiplier to be used when converting
-               tsc-related quantity to nanoseconds
-
-               tsc_shift: shift to be used when converting tsc-related
-               quantity to nanoseconds. This shift will ensure that
-               multiplication with tsc_to_system_mul does not overflow.
-               A positive value denotes a left shift, a negative value
-               a right shift.
-
-               The conversion from tsc to nanoseconds involves an additional
-               right shift by 32 bits. With this information, guests can
-               derive per-CPU time by doing:
-
-                       time = (current_tsc - tsc_timestamp)
-                       if (tsc_shift >= 0)
-                               time <<= tsc_shift;
-                       else
-                               time >>= -tsc_shift;
-                       time = (time * tsc_to_system_mul) >> 32
-                       time = time + system_time
-
-               flags: bits in this field indicate extended capabilities
-               coordinated between the guest and the hypervisor. Availability
-               of specific flags has to be checked in 0x40000001 cpuid leaf.
-               Current flags are:
-
-                flag bit   | cpuid bit    | meaning
-               -------------------------------------------------------------
-                           |              | time measures taken across
-                    0      |      24      | multiple cpus are guaranteed to
-                           |              | be monotonic
-               -------------------------------------------------------------
-                           |              | guest vcpu has been paused by
-                    1      |     N/A      | the host
-                           |              | See 4.70 in api.txt
-               -------------------------------------------------------------
-
-       Availability of this MSR must be checked via bit 3 in 0x4000001 cpuid
-       leaf prior to usage.
-
-
-MSR_KVM_WALL_CLOCK:  0x11
-
-       data and functioning: same as MSR_KVM_WALL_CLOCK_NEW. Use that instead.
-
-       This MSR falls outside the reserved KVM range and may be removed in the
-       future. Its usage is deprecated.
-
-       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
-       leaf prior to usage.
-
-MSR_KVM_SYSTEM_TIME: 0x12
-
-       data and functioning: same as MSR_KVM_SYSTEM_TIME_NEW. Use that instead.
-
-       This MSR falls outside the reserved KVM range and may be removed in the
-       future. Its usage is deprecated.
-
-       Availability of this MSR must be checked via bit 0 in 0x4000001 cpuid
-       leaf prior to usage.
-
-       The suggested algorithm for detecting kvmclock presence is then:
-
-               if (!kvm_para_available())    /* refer to cpuid.txt */
-                       return NON_PRESENT;
-
-               flags = cpuid_eax(0x40000001);
-               if (flags & 3) {
-                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
-                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
-                       return PRESENT;
-               } else if (flags & 0) {
-                       msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
-                       msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
-                       return PRESENT;
-               } else
-                       return NON_PRESENT;
-
-MSR_KVM_ASYNC_PF_EN: 0x4b564d02
-       data: Bits 63-6 hold 64-byte aligned physical address of a
-       64 byte memory area which must be in guest RAM and must be
-       zeroed. Bits 5-3 are reserved and should be zero. Bit 0 is 1
-       when asynchronous page faults are enabled on the vcpu 0 when
-       disabled. Bit 1 is 1 if asynchronous page faults can be injected
-       when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
-       are delivered to L1 as #PF vmexits.  Bit 2 can be set only if
-       KVM_FEATURE_ASYNC_PF_VMEXIT is present in CPUID.
-
-       First 4 byte of 64 byte memory location will be written to by
-       the hypervisor at the time of asynchronous page fault (APF)
-       injection to indicate type of asynchronous page fault. Value
-       of 1 means that the page referred to by the page fault is not
-       present. Value 2 means that the page is now available. Disabling
-       interrupt inhibits APFs. Guest must not enable interrupt
-       before the reason is read, or it may be overwritten by another
-       APF. Since APF uses the same exception vector as regular page
-       fault guest must reset the reason to 0 before it does
-       something that can generate normal page fault.  If during page
-       fault APF reason is 0 it means that this is regular page
-       fault.
-
-       During delivery of type 1 APF cr2 contains a token that will
-       be used to notify a guest when missing page becomes
-       available. When page becomes available type 2 APF is sent with
-       cr2 set to the token associated with the page. There is special
-       kind of token 0xffffffff which tells vcpu that it should wake
-       up all processes waiting for APFs and no individual type 2 APFs
-       will be sent.
-
-       If APF is disabled while there are outstanding APFs, they will
-       not be delivered.
-
-       Currently type 2 APF will be always delivered on the same vcpu as
-       type 1 was, but guest should not rely on that.
-
-MSR_KVM_STEAL_TIME: 0x4b564d03
-
-       data: 64-byte alignment physical address of a memory area which must be
-       in guest RAM, plus an enable bit in bit 0. This memory is expected to
-       hold a copy of the following structure:
-
-       struct kvm_steal_time {
-               __u64 steal;
-               __u32 version;
-               __u32 flags;
-               __u8  preempted;
-               __u8  u8_pad[3];
-               __u32 pad[11];
-       }
-
-       whose data will be filled in by the hypervisor periodically. Only one
-       write, or registration, is needed for each VCPU. The interval between
-       updates of this structure is arbitrary and implementation-dependent.
-       The hypervisor may update this structure at any time it sees fit until
-       anything with bit0 == 0 is written to it. Guest is required to make sure
-       this structure is initialized to zero.
-
-       Fields have the following meanings:
-
-               version: a sequence counter. In other words, guest has to check
-               this field before and after grabbing time information and make
-               sure they are both equal and even. An odd version indicates an
-               in-progress update.
-
-               flags: At this point, always zero. May be used to indicate
-               changes in this structure in the future.
-
-               steal: the amount of time in which this vCPU did not run, in
-               nanoseconds. Time during which the vcpu is idle, will not be
-               reported as steal time.
-
-               preempted: indicate the vCPU who owns this struct is running or
-               not. Non-zero values mean the vCPU has been preempted. Zero
-               means the vCPU is not preempted. NOTE, it is always zero if the
-               the hypervisor doesn't support this field.
-
-MSR_KVM_EOI_EN: 0x4b564d04
-       data: Bit 0 is 1 when PV end of interrupt is enabled on the vcpu; 0
-       when disabled.  Bit 1 is reserved and must be zero.  When PV end of
-       interrupt is enabled (bit 0 set), bits 63-2 hold a 4-byte aligned
-       physical address of a 4 byte memory area which must be in guest RAM and
-       must be zeroed.
-
-       The first, least significant bit of 4 byte memory location will be
-       written to by the hypervisor, typically at the time of interrupt
-       injection.  Value of 1 means that guest can skip writing EOI to the apic
-       (using MSR or MMIO write); instead, it is sufficient to signal
-       EOI by clearing the bit in guest memory - this location will
-       later be polled by the hypervisor.
-       Value of 0 means that the EOI write is required.
-
-       It is always safe for the guest to ignore the optimization and perform
-       the APIC EOI write anyway.
-
-       Hypervisor is guaranteed to only modify this least
-       significant bit while in the current VCPU context, this means that
-       guest does not need to use either lock prefix or memory ordering
-       primitives to synchronise with the hypervisor.
-
-       However, hypervisor can set and clear this memory bit at any time:
-       therefore to make sure hypervisor does not interrupt the
-       guest and clear the least significant bit in the memory area
-       in the window between guest testing it to detect
-       whether it can skip EOI apic write and between guest
-       clearing it to signal EOI to the hypervisor,
-       guest must both read the least significant bit in the memory area and
-       clear it using a single CPU instruction, such as test and clear, or
-       compare and exchange.
-
-MSR_KVM_POLL_CONTROL: 0x4b564d05
-       Control host-side polling.
-
-       data: Bit 0 enables (1) or disables (0) host-side HLT polling logic.
-
-       KVM guests can request the host not to poll on HLT, for example if
-       they are performing polling themselves.
-
diff --git a/Documentation/virtual/kvm/nested-vmx.txt b/Documentation/virtual/kvm/nested-vmx.txt
deleted file mode 100644 (file)
index 97eb135..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-Nested VMX
-==========
-
-Overview
----------
-
-On Intel processors, KVM uses Intel's VMX (Virtual-Machine eXtensions)
-to easily and efficiently run guest operating systems. Normally, these guests
-*cannot* themselves be hypervisors running their own guests, because in VMX,
-guests cannot use VMX instructions.
-
-The "Nested VMX" feature adds this missing capability - of running guest
-hypervisors (which use VMX) with their own nested guests. It does so by
-allowing a guest to use VMX instructions, and correctly and efficiently
-emulating them using the single level of VMX available in the hardware.
-
-We describe in much greater detail the theory behind the nested VMX feature,
-its implementation and its performance characteristics, in the OSDI 2010 paper
-"The Turtles Project: Design and Implementation of Nested Virtualization",
-available at:
-
-       http://www.usenix.org/events/osdi10/tech/full_papers/Ben-Yehuda.pdf
-
-
-Terminology
------------
-
-Single-level virtualization has two levels - the host (KVM) and the guests.
-In nested virtualization, we have three levels: The host (KVM), which we call
-L0, the guest hypervisor, which we call L1, and its nested guest, which we
-call L2.
-
-
-Running nested VMX
-------------------
-
-The nested VMX feature is disabled by default. It can be enabled by giving
-the "nested=1" option to the kvm-intel module.
-
-No modifications are required to user space (qemu). However, qemu's default
-emulated CPU type (qemu64) does not list the "VMX" CPU feature, so it must be
-explicitly enabled, by giving qemu one of the following options:
-
-     -cpu host              (emulated CPU has all features of the real CPU)
-
-     -cpu qemu64,+vmx       (add just the vmx feature to a named CPU type)
-
-
-ABIs
-----
-
-Nested VMX aims to present a standard and (eventually) fully-functional VMX
-implementation for the a guest hypervisor to use. As such, the official
-specification of the ABI that it provides is Intel's VMX specification,
-namely volume 3B of their "Intel 64 and IA-32 Architectures Software
-Developer's Manual". Not all of VMX's features are currently fully supported,
-but the goal is to eventually support them all, starting with the VMX features
-which are used in practice by popular hypervisors (KVM and others).
-
-As a VMX implementation, nested VMX presents a VMCS structure to L1.
-As mandated by the spec, other than the two fields revision_id and abort,
-this structure is *opaque* to its user, who is not supposed to know or care
-about its internal structure. Rather, the structure is accessed through the
-VMREAD and VMWRITE instructions.
-Still, for debugging purposes, KVM developers might be interested to know the
-internals of this structure; This is struct vmcs12 from arch/x86/kvm/vmx.c.
-
-The name "vmcs12" refers to the VMCS that L1 builds for L2. In the code we
-also have "vmcs01", the VMCS that L0 built for L1, and "vmcs02" is the VMCS
-which L0 builds to actually run L2 - how this is done is explained in the
-aforementioned paper.
-
-For convenience, we repeat the content of struct vmcs12 here. If the internals
-of this structure changes, this can break live migration across KVM versions.
-VMCS12_REVISION (from vmx.c) should be changed if struct vmcs12 or its inner
-struct shadow_vmcs is ever changed.
-
-       typedef u64 natural_width;
-       struct __packed vmcs12 {
-               /* According to the Intel spec, a VMCS region must start with
-                * these two user-visible fields */
-               u32 revision_id;
-               u32 abort;
-
-               u32 launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
-               u32 padding[7]; /* room for future expansion */
-
-               u64 io_bitmap_a;
-               u64 io_bitmap_b;
-               u64 msr_bitmap;
-               u64 vm_exit_msr_store_addr;
-               u64 vm_exit_msr_load_addr;
-               u64 vm_entry_msr_load_addr;
-               u64 tsc_offset;
-               u64 virtual_apic_page_addr;
-               u64 apic_access_addr;
-               u64 ept_pointer;
-               u64 guest_physical_address;
-               u64 vmcs_link_pointer;
-               u64 guest_ia32_debugctl;
-               u64 guest_ia32_pat;
-               u64 guest_ia32_efer;
-               u64 guest_pdptr0;
-               u64 guest_pdptr1;
-               u64 guest_pdptr2;
-               u64 guest_pdptr3;
-               u64 host_ia32_pat;
-               u64 host_ia32_efer;
-               u64 padding64[8]; /* room for future expansion */
-               natural_width cr0_guest_host_mask;
-               natural_width cr4_guest_host_mask;
-               natural_width cr0_read_shadow;
-               natural_width cr4_read_shadow;
-               natural_width cr3_target_value0;
-               natural_width cr3_target_value1;
-               natural_width cr3_target_value2;
-               natural_width cr3_target_value3;
-               natural_width exit_qualification;
-               natural_width guest_linear_address;
-               natural_width guest_cr0;
-               natural_width guest_cr3;
-               natural_width guest_cr4;
-               natural_width guest_es_base;
-               natural_width guest_cs_base;
-               natural_width guest_ss_base;
-               natural_width guest_ds_base;
-               natural_width guest_fs_base;
-               natural_width guest_gs_base;
-               natural_width guest_ldtr_base;
-               natural_width guest_tr_base;
-               natural_width guest_gdtr_base;
-               natural_width guest_idtr_base;
-               natural_width guest_dr7;
-               natural_width guest_rsp;
-               natural_width guest_rip;
-               natural_width guest_rflags;
-               natural_width guest_pending_dbg_exceptions;
-               natural_width guest_sysenter_esp;
-               natural_width guest_sysenter_eip;
-               natural_width host_cr0;
-               natural_width host_cr3;
-               natural_width host_cr4;
-               natural_width host_fs_base;
-               natural_width host_gs_base;
-               natural_width host_tr_base;
-               natural_width host_gdtr_base;
-               natural_width host_idtr_base;
-               natural_width host_ia32_sysenter_esp;
-               natural_width host_ia32_sysenter_eip;
-               natural_width host_rsp;
-               natural_width host_rip;
-               natural_width paddingl[8]; /* room for future expansion */
-               u32 pin_based_vm_exec_control;
-               u32 cpu_based_vm_exec_control;
-               u32 exception_bitmap;
-               u32 page_fault_error_code_mask;
-               u32 page_fault_error_code_match;
-               u32 cr3_target_count;
-               u32 vm_exit_controls;
-               u32 vm_exit_msr_store_count;
-               u32 vm_exit_msr_load_count;
-               u32 vm_entry_controls;
-               u32 vm_entry_msr_load_count;
-               u32 vm_entry_intr_info_field;
-               u32 vm_entry_exception_error_code;
-               u32 vm_entry_instruction_len;
-               u32 tpr_threshold;
-               u32 secondary_vm_exec_control;
-               u32 vm_instruction_error;
-               u32 vm_exit_reason;
-               u32 vm_exit_intr_info;
-               u32 vm_exit_intr_error_code;
-               u32 idt_vectoring_info_field;
-               u32 idt_vectoring_error_code;
-               u32 vm_exit_instruction_len;
-               u32 vmx_instruction_info;
-               u32 guest_es_limit;
-               u32 guest_cs_limit;
-               u32 guest_ss_limit;
-               u32 guest_ds_limit;
-               u32 guest_fs_limit;
-               u32 guest_gs_limit;
-               u32 guest_ldtr_limit;
-               u32 guest_tr_limit;
-               u32 guest_gdtr_limit;
-               u32 guest_idtr_limit;
-               u32 guest_es_ar_bytes;
-               u32 guest_cs_ar_bytes;
-               u32 guest_ss_ar_bytes;
-               u32 guest_ds_ar_bytes;
-               u32 guest_fs_ar_bytes;
-               u32 guest_gs_ar_bytes;
-               u32 guest_ldtr_ar_bytes;
-               u32 guest_tr_ar_bytes;
-               u32 guest_interruptibility_info;
-               u32 guest_activity_state;
-               u32 guest_sysenter_cs;
-               u32 host_ia32_sysenter_cs;
-               u32 padding32[8]; /* room for future expansion */
-               u16 virtual_processor_id;
-               u16 guest_es_selector;
-               u16 guest_cs_selector;
-               u16 guest_ss_selector;
-               u16 guest_ds_selector;
-               u16 guest_fs_selector;
-               u16 guest_gs_selector;
-               u16 guest_ldtr_selector;
-               u16 guest_tr_selector;
-               u16 host_es_selector;
-               u16 host_cs_selector;
-               u16 host_ss_selector;
-               u16 host_ds_selector;
-               u16 host_fs_selector;
-               u16 host_gs_selector;
-               u16 host_tr_selector;
-       };
-
-
-Authors
--------
-
-These patches were written by:
-     Abel Gordon, abelg <at> il.ibm.com
-     Nadav Har'El, nyh <at> il.ibm.com
-     Orit Wasserman, oritw <at> il.ibm.com
-     Ben-Ami Yassor, benami <at> il.ibm.com
-     Muli Ben-Yehuda, muli <at> il.ibm.com
-
-With contributions by:
-     Anthony Liguori, aliguori <at> us.ibm.com
-     Mike Day, mdday <at> us.ibm.com
-     Michael Factor, factor <at> il.ibm.com
-     Zvi Dubitzky, dubi <at> il.ibm.com
-
-And valuable reviews by:
-     Avi Kivity, avi <at> redhat.com
-     Gleb Natapov, gleb <at> redhat.com
-     Marcelo Tosatti, mtosatti <at> redhat.com
-     Kevin Tian, kevin.tian <at> intel.com
-     and others.
diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virtual/kvm/ppc-pv.txt
deleted file mode 100644 (file)
index e26115c..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-The PPC KVM paravirtual interface
-=================================
-
-The basic execution principle by which KVM on PowerPC works is to run all kernel
-space code in PR=1 which is user space. This way we trap all privileged
-instructions and can emulate them accordingly.
-
-Unfortunately that is also the downfall. There are quite some privileged
-instructions that needlessly return us to the hypervisor even though they
-could be handled differently.
-
-This is what the PPC PV interface helps with. It takes privileged instructions
-and transforms them into unprivileged ones with some help from the hypervisor.
-This cuts down virtualization costs by about 50% on some of my benchmarks.
-
-The code for that interface can be found in arch/powerpc/kernel/kvm*
-
-Querying for existence
-======================
-
-To find out if we're running on KVM or not, we leverage the device tree. When
-Linux is running on KVM, a node /hypervisor exists. That node contains a
-compatible property with the value "linux,kvm".
-
-Once you determined you're running under a PV capable KVM, you can now use
-hypercalls as described below.
-
-KVM hypercalls
-==============
-
-Inside the device tree's /hypervisor node there's a property called
-'hypercall-instructions'. This property contains at most 4 opcodes that make
-up the hypercall. To call a hypercall, just call these instructions.
-
-The parameters are as follows:
-
-       Register        IN                      OUT
-
-       r0              -                       volatile
-       r3              1st parameter           Return code
-       r4              2nd parameter           1st output value
-       r5              3rd parameter           2nd output value
-       r6              4th parameter           3rd output value
-       r7              5th parameter           4th output value
-       r8              6th parameter           5th output value
-       r9              7th parameter           6th output value
-       r10             8th parameter           7th output value
-       r11             hypercall number        8th output value
-       r12             -                       volatile
-
-Hypercall definitions are shared in generic code, so the same hypercall numbers
-apply for x86 and powerpc alike with the exception that each KVM hypercall
-also needs to be ORed with the KVM vendor code which is (42 << 16).
-
-Return codes can be as follows:
-
-       Code            Meaning
-
-       0               Success
-       12              Hypercall not implemented
-       <0              Error
-
-The magic page
-==============
-
-To enable communication between the hypervisor and guest there is a new shared
-page that contains parts of supervisor visible register state. The guest can
-map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
-
-With this hypercall issued the guest always gets the magic page mapped at the
-desired location. The first parameter indicates the effective address when the
-MMU is enabled. The second parameter indicates the address in real mode, if
-applicable to the target. For now, we always map the page to -4096. This way we
-can access it using absolute load and store functions. The following
-instruction reads the first field of the magic page:
-
-       ld      rX, -4096(0)
-
-The interface is designed to be extensible should there be need later to add
-additional registers to the magic page. If you add fields to the magic page,
-also define a new hypercall feature to indicate that the host can give you more
-registers. Only if the host supports the additional features, make use of them.
-
-The magic page layout is described by struct kvm_vcpu_arch_shared
-in arch/powerpc/include/asm/kvm_para.h.
-
-Magic page features
-===================
-
-When mapping the magic page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE,
-a second return value is passed to the guest. This second return value contains
-a bitmap of available features inside the magic page.
-
-The following enhancements to the magic page are currently available:
-
-  KVM_MAGIC_FEAT_SR            Maps SR registers r/w in the magic page
-  KVM_MAGIC_FEAT_MAS0_TO_SPRG7 Maps MASn, ESR, PIR and high SPRGs
-
-For enhanced features in the magic page, please check for the existence of the
-feature before using them!
-
-Magic page flags
-================
-
-In addition to features that indicate whether a host is capable of a particular
-feature we also have a channel for a guest to tell the guest whether it's capable
-of something. This is what we call "flags".
-
-Flags are passed to the host in the low 12 bits of the Effective Address.
-
-The following flags are currently available for a guest to expose:
-
-  MAGIC_PAGE_FLAG_NOT_MAPPED_NX Guest handles NX bits correctly wrt magic page
-
-MSR bits
-========
-
-The MSR contains bits that require hypervisor intervention and bits that do
-not require direct hypervisor intervention because they only get interpreted
-when entering the guest or don't have any impact on the hypervisor's behavior.
-
-The following bits are safe to be set inside the guest:
-
-  MSR_EE
-  MSR_RI
-
-If any other bit changes in the MSR, please still use mtmsr(d).
-
-Patched instructions
-====================
-
-The "ld" and "std" instructions are transformed to "lwz" and "stw" instructions
-respectively on 32 bit systems with an added offset of 4 to accommodate for big
-endianness.
-
-The following is a list of mapping the Linux kernel performs when running as
-guest. Implementing any of those mappings is optional, as the instruction traps
-also act on the shared page. So calling privileged instructions still works as
-before.
-
-From                   To
-====                   ==
-
-mfmsr  rX              ld      rX, magic_page->msr
-mfsprg rX, 0           ld      rX, magic_page->sprg0
-mfsprg rX, 1           ld      rX, magic_page->sprg1
-mfsprg rX, 2           ld      rX, magic_page->sprg2
-mfsprg rX, 3           ld      rX, magic_page->sprg3
-mfsrr0 rX              ld      rX, magic_page->srr0
-mfsrr1 rX              ld      rX, magic_page->srr1
-mfdar  rX              ld      rX, magic_page->dar
-mfdsisr        rX              lwz     rX, magic_page->dsisr
-
-mtmsr  rX              std     rX, magic_page->msr
-mtsprg 0, rX           std     rX, magic_page->sprg0
-mtsprg 1, rX           std     rX, magic_page->sprg1
-mtsprg 2, rX           std     rX, magic_page->sprg2
-mtsprg 3, rX           std     rX, magic_page->sprg3
-mtsrr0 rX              std     rX, magic_page->srr0
-mtsrr1 rX              std     rX, magic_page->srr1
-mtdar  rX              std     rX, magic_page->dar
-mtdsisr        rX              stw     rX, magic_page->dsisr
-
-tlbsync                        nop
-
-mtmsrd rX, 0           b       <special mtmsr section>
-mtmsr  rX              b       <special mtmsr section>
-
-mtmsrd rX, 1           b       <special mtmsrd section>
-
-[Book3S only]
-mtsrin rX, rY          b       <special mtsrin section>
-
-[BookE only]
-wrteei [0|1]           b       <special wrteei section>
-
-
-Some instructions require more logic to determine what's going on than a load
-or store instruction can deliver. To enable patching of those, we keep some
-RAM around where we can live translate instructions to. What happens is the
-following:
-
-       1) copy emulation code to memory
-       2) patch that code to fit the emulated instruction
-       3) patch that code to return to the original pc + 4
-       4) patch the original instruction to branch to the new code
-
-That way we can inject an arbitrary amount of code as replacement for a single
-instruction. This allows us to check for pending interrupts when setting EE=1
-for example.
-
-Hypercall ABIs in KVM on PowerPC
-=================================
-1) KVM hypercalls (ePAPR)
-
-These are ePAPR compliant hypercall implementation (mentioned above). Even
-generic hypercalls are implemented here, like the ePAPR idle hcall. These are
-available on all targets.
-
-2) PAPR hypercalls
-
-PAPR hypercalls are needed to run server PowerPC PAPR guests (-M pseries in QEMU).
-These are the same hypercalls that pHyp, the POWER hypervisor implements. Some of
-them are handled in the kernel, some are handled in user space. This is only
-available on book3s_64.
-
-3) OSI hypercalls
-
-Mac-on-Linux is another user of KVM on PowerPC, which has its own hypercall (long
-before KVM). This is supported to maintain compatibility. All these hypercalls get
-forwarded to user space. This is only useful on book3s_32, but can be used with
-book3s_64 as well.
diff --git a/Documentation/virtual/kvm/review-checklist.txt b/Documentation/virtual/kvm/review-checklist.txt
deleted file mode 100644 (file)
index a83b276..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-Review checklist for kvm patches
-================================
-
-1.  The patch must follow Documentation/process/coding-style.rst and
-    Documentation/process/submitting-patches.rst.
-
-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 discoverable using KVM_CHECK_EXTENSION
-
-4.  New state must include support for save/restore.
-
-5.  New features must default to off (userspace should explicitly request them).
-    Performance improvements can and should default to on.
-
-6.  New cpu features should be exposed via KVM_GET_SUPPORTED_CPUID2
-
-7.  Emulator changes should be accompanied by unit tests for qemu-kvm.git
-    kvm/test directory.
-
-8.  Changes should be vendor neutral when possible.  Changes to common code
-    are better than duplicating changes to vendor code.
-
-9.  Similarly, prefer changes to arch independent code than to arch dependent
-    code.
-
-10. User/kernel interfaces and guest/host interfaces must be 64-bit clean
-    (all variables and sizes naturally aligned on 64-bit; use specific types
-    only - u64 rather than ulong).
-
-11. New guest visible features must either be documented in a hardware manual
-    or be accompanied by documentation.
-
-12. Features must be robust against reset and kexec - for example, shared
-    host/guest memory must be unshared to prevent the host from writing to
-    guest memory that the guest has not reserved for this purpose.
diff --git a/Documentation/virtual/kvm/s390-diag.txt b/Documentation/virtual/kvm/s390-diag.txt
deleted file mode 100644 (file)
index 7c52e5f..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-The s390 DIAGNOSE call on KVM
-=============================
-
-KVM on s390 supports the DIAGNOSE call for making hypercalls, both for
-native hypercalls and for selected hypercalls found on other s390
-hypervisors.
-
-Note that bits are numbered as by the usual s390 convention (most significant
-bit on the left).
-
-
-General remarks
----------------
-
-DIAGNOSE calls by the guest cause a mandatory intercept. This implies
-all supported DIAGNOSE calls need to be handled by either KVM or its
-userspace.
-
-All DIAGNOSE calls supported by KVM use the RS-a format:
-
---------------------------------------
-|  '83'  | R1 | R3 | B2 |     D2     |
---------------------------------------
-0        8    12   16   20           31
-
-The second-operand address (obtained by the base/displacement calculation)
-is not used to address data. Instead, bits 48-63 of this address specify
-the function code, and bits 0-47 are ignored.
-
-The supported DIAGNOSE function codes vary by the userspace used. For
-DIAGNOSE function codes not specific to KVM, please refer to the
-documentation for the s390 hypervisors defining them.
-
-
-DIAGNOSE function code 'X'500' - KVM virtio functions
------------------------------------------------------
-
-If the function code specifies 0x500, various virtio-related functions
-are performed.
-
-General register 1 contains the virtio subfunction code. Supported
-virtio subfunctions depend on KVM's userspace. Generally, userspace
-provides either s390-virtio (subcodes 0-2) or virtio-ccw (subcode 3).
-
-Upon completion of the DIAGNOSE instruction, general register 2 contains
-the function's return code, which is either a return code or a subcode
-specific value.
-
-Subcode 0 - s390-virtio notification and early console printk
-    Handled by userspace.
-
-Subcode 1 - s390-virtio reset
-    Handled by userspace.
-
-Subcode 2 - s390-virtio set status
-    Handled by userspace.
-
-Subcode 3 - virtio-ccw notification
-    Handled by either userspace or KVM (ioeventfd case).
-
-    General register 2 contains a subchannel-identification word denoting
-    the subchannel of the virtio-ccw proxy device to be notified.
-
-    General register 3 contains the number of the virtqueue to be notified.
-
-    General register 4 contains a 64bit identifier for KVM usage (the
-    kvm_io_bus cookie). If general register 4 does not contain a valid
-    identifier, it is ignored.
-
-    After completion of the DIAGNOSE call, general register 2 may contain
-    a 64bit identifier (in the kvm_io_bus cookie case), or a negative
-    error value, if an internal error occurred.
-
-    See also the virtio standard for a discussion of this hypercall.
-
-
-DIAGNOSE function code 'X'501 - KVM breakpoint
-----------------------------------------------
-
-If the function code specifies 0x501, breakpoint functions may be performed.
-This function code is handled by userspace.
-
-This diagnose function code has no subfunctions and uses no parameters.
diff --git a/Documentation/virtual/kvm/timekeeping.txt b/Documentation/virtual/kvm/timekeeping.txt
deleted file mode 100644 (file)
index 76808a1..0000000
+++ /dev/null
@@ -1,612 +0,0 @@
-
-       Timekeeping Virtualization for X86-Based Architectures
-
-       Zachary Amsden <zamsden@redhat.com>
-       Copyright (c) 2010, Red Hat.  All rights reserved.
-
-1) Overview
-2) Timing Devices
-3) TSC Hardware
-4) Virtualization Problems
-
-=========================================================================
-
-1) Overview
-
-One of the most complicated parts of the X86 platform, and specifically,
-the virtualization of this platform is the plethora of timing devices available
-and the complexity of emulating those devices.  In addition, virtualization of
-time introduces a new set of challenges because it introduces a multiplexed
-division of time beyond the control of the guest CPU.
-
-First, we will describe the various timekeeping hardware available, then
-present some of the problems which arise and solutions available, giving
-specific recommendations for certain classes of KVM guests.
-
-The purpose of this document is to collect data and information relevant to
-timekeeping which may be difficult to find elsewhere, specifically,
-information relevant to KVM and hardware-based virtualization.
-
-=========================================================================
-
-2) Timing Devices
-
-First we discuss the basic hardware devices available.  TSC and the related
-KVM clock are special enough to warrant a full exposition and are described in
-the following section.
-
-2.1) i8254 - PIT
-
-One of the first timer devices available is the programmable interrupt timer,
-or PIT.  The PIT has a fixed frequency 1.193182 MHz base clock and three
-channels which can be programmed to deliver periodic or one-shot interrupts.
-These three channels can be configured in different modes and have individual
-counters.  Channel 1 and 2 were not available for general use in the original
-IBM PC, and historically were connected to control RAM refresh and the PC
-speaker.  Now the PIT is typically integrated as part of an emulated chipset
-and a separate physical PIT is not used.
-
-The PIT uses I/O ports 0x40 - 0x43.  Access to the 16-bit counters is done
-using single or multiple byte access to the I/O ports.  There are 6 modes
-available, but not all modes are available to all timers, as only timer 2
-has a connected gate input, required for modes 1 and 5.  The gate line is
-controlled by port 61h, bit 0, as illustrated in the following diagram.
-
- --------------             ----------------
-|              |           |                |
-|  1.1932 MHz  |---------->| CLOCK      OUT | ---------> IRQ 0
-|    Clock     |   |       |                |
- --------------    |    +->| GATE  TIMER 0  |
-                   |        ----------------
-                   |
-                   |        ----------------
-                   |       |                |
-                   |------>| CLOCK      OUT | ---------> 66.3 KHZ DRAM
-                   |       |                |            (aka /dev/null)
-                   |    +->| GATE  TIMER 1  |
-                   |        ----------------
-                   |
-                   |        ----------------
-                   |       |                |
-                   |------>| CLOCK      OUT | ---------> Port 61h, bit 5
-                           |                |      |
-Port 61h, bit 0 ---------->| GATE  TIMER 2  |       \_.----   ____
-                            ----------------         _|    )--|LPF|---Speaker
-                                                    / *----   \___/
-Port 61h, bit 1 -----------------------------------/
-
-The timer modes are now described.
-
-Mode 0: Single Timeout.   This is a one-shot software timeout that counts down
- when the gate is high (always true for timers 0 and 1).  When the count
- reaches zero, the output goes high.
-
-Mode 1: Triggered One-shot.  The output is initially set high.  When the gate
- line is set high, a countdown is initiated (which does not stop if the gate is
- lowered), during which the output is set low.  When the count reaches zero,
- the output goes high.
-
-Mode 2: Rate Generator.  The output is initially set high.  When the countdown
- reaches 1, the output goes low for one count and then returns high.  The value
- is reloaded and the countdown automatically resumes.  If the gate line goes
- low, the count is halted.  If the output is low when the gate is lowered, the
- output automatically goes high (this only affects timer 2).
-
-Mode 3: Square Wave.   This generates a high / low square wave.  The count
- determines the length of the pulse, which alternates between high and low
- when zero is reached.  The count only proceeds when gate is high and is
- automatically reloaded on reaching zero.  The count is decremented twice at
- each clock to generate a full high / low cycle at the full periodic rate.
- If the count is even, the clock remains high for N/2 counts and low for N/2
- counts; if the clock is odd, the clock is high for (N+1)/2 counts and low
- for (N-1)/2 counts.  Only even values are latched by the counter, so odd
- values are not observed when reading.  This is the intended mode for timer 2,
- which generates sine-like tones by low-pass filtering the square wave output.
-
-Mode 4: Software Strobe.  After programming this mode and loading the counter,
- the output remains high until the counter reaches zero.  Then the output
- goes low for 1 clock cycle and returns high.  The counter is not reloaded.
- Counting only occurs when gate is high.
-
-Mode 5: Hardware Strobe.  After programming and loading the counter, the
- output remains high.  When the gate is raised, a countdown is initiated
- (which does not stop if the gate is lowered).  When the counter reaches zero,
- the output goes low for 1 clock cycle and then returns high.  The counter is
- not reloaded.
-
-In addition to normal binary counting, the PIT supports BCD counting.  The
-command port, 0x43 is used to set the counter and mode for each of the three
-timers.
-
-PIT commands, issued to port 0x43, using the following bit encoding:
-
-Bit 7-4: Command (See table below)
-Bit 3-1: Mode (000 = Mode 0, 101 = Mode 5, 11X = undefined)
-Bit 0  : Binary (0) / BCD (1)
-
-Command table:
-
-0000 - Latch Timer 0 count for port 0x40
-       sample and hold the count to be read in port 0x40;
-       additional commands ignored until counter is read;
-       mode bits ignored.
-
-0001 - Set Timer 0 LSB mode for port 0x40
-       set timer to read LSB only and force MSB to zero;
-       mode bits set timer mode
-
-0010 - Set Timer 0 MSB mode for port 0x40
-       set timer to read MSB only and force LSB to zero;
-       mode bits set timer mode
-
-0011 - Set Timer 0 16-bit mode for port 0x40
-       set timer to read / write LSB first, then MSB;
-       mode bits set timer mode
-
-0100 - Latch Timer 1 count for port 0x41 - as described above
-0101 - Set Timer 1 LSB mode for port 0x41 - as described above
-0110 - Set Timer 1 MSB mode for port 0x41 - as described above
-0111 - Set Timer 1 16-bit mode for port 0x41 - as described above
-
-1000 - Latch Timer 2 count for port 0x42 - as described above
-1001 - Set Timer 2 LSB mode for port 0x42 - as described above
-1010 - Set Timer 2 MSB mode for port 0x42 - as described above
-1011 - Set Timer 2 16-bit mode for port 0x42 as described above
-
-1101 - General counter latch
-       Latch combination of counters into corresponding ports
-       Bit 3 = Counter 2
-       Bit 2 = Counter 1
-       Bit 1 = Counter 0
-       Bit 0 = Unused
-
-1110 - Latch timer status
-       Latch combination of counter mode into corresponding ports
-       Bit 3 = Counter 2
-       Bit 2 = Counter 1
-       Bit 1 = Counter 0
-
-       The output of ports 0x40-0x42 following this command will be:
-
-       Bit 7 = Output pin
-       Bit 6 = Count loaded (0 if timer has expired)
-       Bit 5-4 = Read / Write mode
-           01 = MSB only
-           10 = LSB only
-           11 = LSB / MSB (16-bit)
-       Bit 3-1 = Mode
-       Bit 0 = Binary (0) / BCD mode (1)
-
-2.2) RTC
-
-The second device which was available in the original PC was the MC146818 real
-time clock.  The original device is now obsolete, and usually emulated by the
-system chipset, sometimes by an HPET and some frankenstein IRQ routing.
-
-The RTC is accessed through CMOS variables, which uses an index register to
-control which bytes are read.  Since there is only one index register, read
-of the CMOS and read of the RTC require lock protection (in addition, it is
-dangerous to allow userspace utilities such as hwclock to have direct RTC
-access, as they could corrupt kernel reads and writes of CMOS memory).
-
-The RTC generates an interrupt which is usually routed to IRQ 8.  The interrupt
-can function as a periodic timer, an additional once a day alarm, and can issue
-interrupts after an update of the CMOS registers by the MC146818 is complete.
-The type of interrupt is signalled in the RTC status registers.
-
-The RTC will update the current time fields by battery power even while the
-system is off.  The current time fields should not be read while an update is
-in progress, as indicated in the status register.
-
-The clock uses a 32.768kHz crystal, so bits 6-4 of register A should be
-programmed to a 32kHz divider if the RTC is to count seconds.
-
-This is the RAM map originally used for the RTC/CMOS:
-
-Location    Size    Description
-------------------------------------------
-00h         byte    Current second (BCD)
-01h         byte    Seconds alarm (BCD)
-02h         byte    Current minute (BCD)
-03h         byte    Minutes alarm (BCD)
-04h         byte    Current hour (BCD)
-05h         byte    Hours alarm (BCD)
-06h         byte    Current day of week (BCD)
-07h         byte    Current day of month (BCD)
-08h         byte    Current month (BCD)
-09h         byte    Current year (BCD)
-0Ah         byte    Register A
-                       bit 7   = Update in progress
-                       bit 6-4 = Divider for clock
-                                  000 = 4.194 MHz
-                                  001 = 1.049 MHz
-                                  010 = 32 kHz
-                                  10X = test modes
-                                  110 = reset / disable
-                                  111 = reset / disable
-                       bit 3-0 = Rate selection for periodic interrupt
-                                  000 = periodic timer disabled
-                                  001 = 3.90625 uS
-                                  010 = 7.8125 uS
-                                  011 = .122070 mS
-                                  100 = .244141 mS
-                                     ...
-                                 1101 = 125 mS
-                                 1110 = 250 mS
-                                 1111 = 500 mS
-0Bh         byte    Register B
-                       bit 7   = Run (0) / Halt (1)
-                       bit 6   = Periodic interrupt enable
-                       bit 5   = Alarm interrupt enable
-                       bit 4   = Update-ended interrupt enable
-                       bit 3   = Square wave interrupt enable
-                       bit 2   = BCD calendar (0) / Binary (1)
-                       bit 1   = 12-hour mode (0) / 24-hour mode (1)
-                       bit 0   = 0 (DST off) / 1 (DST enabled)
-OCh         byte    Register C (read only)
-                       bit 7   = interrupt request flag (IRQF)
-                       bit 6   = periodic interrupt flag (PF)
-                       bit 5   = alarm interrupt flag (AF)
-                       bit 4   = update interrupt flag (UF)
-                       bit 3-0 = reserved
-ODh         byte    Register D (read only)
-                       bit 7   = RTC has power
-                       bit 6-0 = reserved
-32h         byte    Current century BCD (*)
-  (*) location vendor specific and now determined from ACPI global tables
-
-2.3) APIC
-
-On Pentium and later processors, an on-board timer is available to each CPU
-as part of the Advanced Programmable Interrupt Controller.  The APIC is
-accessed through memory-mapped registers and provides interrupt service to each
-CPU, used for IPIs and local timer interrupts.
-
-Although in theory the APIC is a safe and stable source for local interrupts,
-in practice, many bugs and glitches have occurred due to the special nature of
-the APIC CPU-local memory-mapped hardware.  Beware that CPU errata may affect
-the use of the APIC and that workarounds may be required.  In addition, some of
-these workarounds pose unique constraints for virtualization - requiring either
-extra overhead incurred from extra reads of memory-mapped I/O or additional
-functionality that may be more computationally expensive to implement.
-
-Since the APIC is documented quite well in the Intel and AMD manuals, we will
-avoid repetition of the detail here.  It should be pointed out that the APIC
-timer is programmed through the LVT (local vector timer) register, is capable
-of one-shot or periodic operation, and is based on the bus clock divided down
-by the programmable divider register.
-
-2.4) HPET
-
-HPET is quite complex, and was originally intended to replace the PIT / RTC
-support of the X86 PC.  It remains to be seen whether that will be the case, as
-the de facto standard of PC hardware is to emulate these older devices.  Some
-systems designated as legacy free may support only the HPET as a hardware timer
-device.
-
-The HPET spec is rather loose and vague, requiring at least 3 hardware timers,
-but allowing implementation freedom to support many more.  It also imposes no
-fixed rate on the timer frequency, but does impose some extremal values on
-frequency, error and slew.
-
-In general, the HPET is recommended as a high precision (compared to PIT /RTC)
-time source which is independent of local variation (as there is only one HPET
-in any given system).  The HPET is also memory-mapped, and its presence is
-indicated through ACPI tables by the BIOS.
-
-Detailed specification of the HPET is beyond the current scope of this
-document, as it is also very well documented elsewhere.
-
-2.5) Offboard Timers
-
-Several cards, both proprietary (watchdog boards) and commonplace (e1000) have
-timing chips built into the cards which may have registers which are accessible
-to kernel or user drivers.  To the author's knowledge, using these to generate
-a clocksource for a Linux or other kernel has not yet been attempted and is in
-general frowned upon as not playing by the agreed rules of the game.  Such a
-timer device would require additional support to be virtualized properly and is
-not considered important at this time as no known operating system does this.
-
-=========================================================================
-
-3) TSC Hardware
-
-The TSC or time stamp counter is relatively simple in theory; it counts
-instruction cycles issued by the processor, which can be used as a measure of
-time.  In practice, due to a number of problems, it is the most complicated
-timekeeping device to use.
-
-The TSC is represented internally as a 64-bit MSR which can be read with the
-RDMSR, RDTSC, or RDTSCP (when available) instructions.  In the past, hardware
-limitations made it possible to write the TSC, but generally on old hardware it
-was only possible to write the low 32-bits of the 64-bit counter, and the upper
-32-bits of the counter were cleared.  Now, however, on Intel processors family
-0Fh, for models 3, 4 and 6, and family 06h, models e and f, this restriction
-has been lifted and all 64-bits are writable.  On AMD systems, the ability to
-write the TSC MSR is not an architectural guarantee.
-
-The TSC is accessible from CPL-0 and conditionally, for CPL > 0 software by
-means of the CR4.TSD bit, which when enabled, disables CPL > 0 TSC access.
-
-Some vendors have implemented an additional instruction, RDTSCP, which returns
-atomically not just the TSC, but an indicator which corresponds to the
-processor number.  This can be used to index into an array of TSC variables to
-determine offset information in SMP systems where TSCs are not synchronized.
-The presence of this instruction must be determined by consulting CPUID feature
-bits.
-
-Both VMX and SVM provide extension fields in the virtualization hardware which
-allows the guest visible TSC to be offset by a constant.  Newer implementations
-promise to allow the TSC to additionally be scaled, but this hardware is not
-yet widely available.
-
-3.1) TSC synchronization
-
-The TSC is a CPU-local clock in most implementations.  This means, on SMP
-platforms, the TSCs of different CPUs may start at different times depending
-on when the CPUs are powered on.  Generally, CPUs on the same die will share
-the same clock, however, this is not always the case.
-
-The BIOS may attempt to resynchronize the TSCs during the poweron process and
-the operating system or other system software may attempt to do this as well.
-Several hardware limitations make the problem worse - if it is not possible to
-write the full 64-bits of the TSC, it may be impossible to match the TSC in
-newly arriving CPUs to that of the rest of the system, resulting in
-unsynchronized TSCs.  This may be done by BIOS or system software, but in
-practice, getting a perfectly synchronized TSC will not be possible unless all
-values are read from the same clock, which generally only is possible on single
-socket systems or those with special hardware support.
-
-3.2) TSC and CPU hotplug
-
-As touched on already, CPUs which arrive later than the boot time of the system
-may not have a TSC value that is synchronized with the rest of the system.
-Either system software, BIOS, or SMM code may actually try to establish the TSC
-to a value matching the rest of the system, but a perfect match is usually not
-a guarantee.  This can have the effect of bringing a system from a state where
-TSC is synchronized back to a state where TSC synchronization flaws, however
-small, may be exposed to the OS and any virtualization environment.
-
-3.3) TSC and multi-socket / NUMA
-
-Multi-socket systems, especially large multi-socket systems are likely to have
-individual clocksources rather than a single, universally distributed clock.
-Since these clocks are driven by different crystals, they will not have
-perfectly matched frequency, and temperature and electrical variations will
-cause the CPU clocks, and thus the TSCs to drift over time.  Depending on the
-exact clock and bus design, the drift may or may not be fixed in absolute
-error, and may accumulate over time.
-
-In addition, very large systems may deliberately slew the clocks of individual
-cores.  This technique, known as spread-spectrum clocking, reduces EMI at the
-clock frequency and harmonics of it, which may be required to pass FCC
-standards for telecommunications and computer equipment.
-
-It is recommended not to trust the TSCs to remain synchronized on NUMA or
-multiple socket systems for these reasons.
-
-3.4) TSC and C-states
-
-C-states, or idling states of the processor, especially C1E and deeper sleep
-states may be problematic for TSC as well.  The TSC may stop advancing in such
-a state, resulting in a TSC which is behind that of other CPUs when execution
-is resumed.  Such CPUs must be detected and flagged by the operating system
-based on CPU and chipset identifications.
-
-The TSC in such a case may be corrected by catching it up to a known external
-clocksource.
-
-3.5) TSC frequency change / P-states
-
-To make things slightly more interesting, some CPUs may change frequency.  They
-may or may not run the TSC at the same rate, and because the frequency change
-may be staggered or slewed, at some points in time, the TSC rate may not be
-known other than falling within a range of values.  In this case, the TSC will
-not be a stable time source, and must be calibrated against a known, stable,
-external clock to be a usable source of time.
-
-Whether the TSC runs at a constant rate or scales with the P-state is model
-dependent and must be determined by inspecting CPUID, chipset or vendor
-specific MSR fields.
-
-In addition, some vendors have known bugs where the P-state is actually
-compensated for properly during normal operation, but when the processor is
-inactive, the P-state may be raised temporarily to service cache misses from
-other processors.  In such cases, the TSC on halted CPUs could advance faster
-than that of non-halted processors.  AMD Turion processors are known to have
-this problem.
-
-3.6) TSC and STPCLK / T-states
-
-External signals given to the processor may also have the effect of stopping
-the TSC.  This is typically done for thermal emergency power control to prevent
-an overheating condition, and typically, there is no way to detect that this
-condition has happened.
-
-3.7) TSC virtualization - VMX
-
-VMX provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
-instructions, which is enough for full virtualization of TSC in any manner.  In
-addition, VMX allows passing through the host TSC plus an additional TSC_OFFSET
-field specified in the VMCS.  Special instructions must be used to read and
-write the VMCS field.
-
-3.8) TSC virtualization - SVM
-
-SVM provides conditional trapping of RDTSC, RDMSR, WRMSR and RDTSCP
-instructions, which is enough for full virtualization of TSC in any manner.  In
-addition, SVM allows passing through the host TSC plus an additional offset
-field specified in the SVM control block.
-
-3.9) TSC feature bits in Linux
-
-In summary, there is no way to guarantee the TSC remains in perfect
-synchronization unless it is explicitly guaranteed by the architecture.  Even
-if so, the TSCs in multi-sockets or NUMA systems may still run independently
-despite being locally consistent.
-
-The following feature bits are used by Linux to signal various TSC attributes,
-but they can only be taken to be meaningful for UP or single node systems.
-
-X86_FEATURE_TSC                : The TSC is available in hardware
-X86_FEATURE_RDTSCP             : The RDTSCP instruction is available
-X86_FEATURE_CONSTANT_TSC       : The TSC rate is unchanged with P-states
-X86_FEATURE_NONSTOP_TSC                : The TSC does not stop in C-states
-X86_FEATURE_TSC_RELIABLE       : TSC sync checks are skipped (VMware)
-
-4) Virtualization Problems
-
-Timekeeping is especially problematic for virtualization because a number of
-challenges arise.  The most obvious problem is that time is now shared between
-the host and, potentially, a number of virtual machines.  Thus the virtual
-operating system does not run with 100% usage of the CPU, despite the fact that
-it may very well make that assumption.  It may expect it to remain true to very
-exacting bounds when interrupt sources are disabled, but in reality only its
-virtual interrupt sources are disabled, and the machine may still be preempted
-at any time.  This causes problems as the passage of real time, the injection
-of machine interrupts and the associated clock sources are no longer completely
-synchronized with real time.
-
-This same problem can occur on native hardware to a degree, as SMM mode may
-steal cycles from the naturally on X86 systems when SMM mode is used by the
-BIOS, but not in such an extreme fashion.  However, the fact that SMM mode may
-cause similar problems to virtualization makes it a good justification for
-solving many of these problems on bare metal.
-
-4.1) Interrupt clocking
-
-One of the most immediate problems that occurs with legacy operating systems
-is that the system timekeeping routines are often designed to keep track of
-time by counting periodic interrupts.  These interrupts may come from the PIT
-or the RTC, but the problem is the same: the host virtualization engine may not
-be able to deliver the proper number of interrupts per second, and so guest
-time may fall behind.  This is especially problematic if a high interrupt rate
-is selected, such as 1000 HZ, which is unfortunately the default for many Linux
-guests.
-
-There are three approaches to solving this problem; first, it may be possible
-to simply ignore it.  Guests which have a separate time source for tracking
-'wall clock' or 'real time' may not need any adjustment of their interrupts to
-maintain proper time.  If this is not sufficient, it may be necessary to inject
-additional interrupts into the guest in order to increase the effective
-interrupt rate.  This approach leads to complications in extreme conditions,
-where host load or guest lag is too much to compensate for, and thus another
-solution to the problem has risen: the guest may need to become aware of lost
-ticks and compensate for them internally.  Although promising in theory, the
-implementation of this policy in Linux has been extremely error prone, and a
-number of buggy variants of lost tick compensation are distributed across
-commonly used Linux systems.
-
-Windows uses periodic RTC clocking as a means of keeping time internally, and
-thus requires interrupt slewing to keep proper time.  It does use a low enough
-rate (ed: is it 18.2 Hz?) however that it has not yet been a problem in
-practice.
-
-4.2) TSC sampling and serialization
-
-As the highest precision time source available, the cycle counter of the CPU
-has aroused much interest from developers.  As explained above, this timer has
-many problems unique to its nature as a local, potentially unstable and
-potentially unsynchronized source.  One issue which is not unique to the TSC,
-but is highlighted because of its very precise nature is sampling delay.  By
-definition, the counter, once read is already old.  However, it is also
-possible for the counter to be read ahead of the actual use of the result.
-This is a consequence of the superscalar execution of the instruction stream,
-which may execute instructions out of order.  Such execution is called
-non-serialized.  Forcing serialized execution is necessary for precise
-measurement with the TSC, and requires a serializing instruction, such as CPUID
-or an MSR read.
-
-Since CPUID may actually be virtualized by a trap and emulate mechanism, this
-serialization can pose a performance issue for hardware virtualization.  An
-accurate time stamp counter reading may therefore not always be available, and
-it may be necessary for an implementation to guard against "backwards" reads of
-the TSC as seen from other CPUs, even in an otherwise perfectly synchronized
-system.
-
-4.3) Timespec aliasing
-
-Additionally, this lack of serialization from the TSC poses another challenge
-when using results of the TSC when measured against another time source.  As
-the TSC is much higher precision, many possible values of the TSC may be read
-while another clock is still expressing the same value.
-
-That is, you may read (T,T+10) while external clock C maintains the same value.
-Due to non-serialized reads, you may actually end up with a range which
-fluctuates - from (T-1.. T+10).  Thus, any time calculated from a TSC, but
-calibrated against an external value may have a range of valid values.
-Re-calibrating this computation may actually cause time, as computed after the
-calibration, to go backwards, compared with time computed before the
-calibration.
-
-This problem is particularly pronounced with an internal time source in Linux,
-the kernel time, which is expressed in the theoretically high resolution
-timespec - but which advances in much larger granularity intervals, sometimes
-at the rate of jiffies, and possibly in catchup modes, at a much larger step.
-
-This aliasing requires care in the computation and recalibration of kvmclock
-and any other values derived from TSC computation (such as TSC virtualization
-itself).
-
-4.4) Migration
-
-Migration of a virtual machine raises problems for timekeeping in two ways.
-First, the migration itself may take time, during which interrupts cannot be
-delivered, and after which, the guest time may need to be caught up.  NTP may
-be able to help to some degree here, as the clock correction required is
-typically small enough to fall in the NTP-correctable window.
-
-An additional concern is that timers based off the TSC (or HPET, if the raw bus
-clock is exposed) may now be running at different rates, requiring compensation
-in some way in the hypervisor by virtualizing these timers.  In addition,
-migrating to a faster machine may preclude the use of a passthrough TSC, as a
-faster clock cannot be made visible to a guest without the potential of time
-advancing faster than usual.  A slower clock is less of a problem, as it can
-always be caught up to the original rate.  KVM clock avoids these problems by
-simply storing multipliers and offsets against the TSC for the guest to convert
-back into nanosecond resolution values.
-
-4.5) Scheduling
-
-Since scheduling may be based on precise timing and firing of interrupts, the
-scheduling algorithms of an operating system may be adversely affected by
-virtualization.  In theory, the effect is random and should be universally
-distributed, but in contrived as well as real scenarios (guest device access,
-causes of virtualization exits, possible context switch), this may not always
-be the case.  The effect of this has not been well studied.
-
-In an attempt to work around this, several implementations have provided a
-paravirtualized scheduler clock, which reveals the true amount of CPU time for
-which a virtual machine has been running.
-
-4.6) Watchdogs
-
-Watchdog timers, such as the lock detector in Linux may fire accidentally when
-running under hardware virtualization due to timer interrupts being delayed or
-misinterpretation of the passage of real time.  Usually, these warnings are
-spurious and can be ignored, but in some circumstances it may be necessary to
-disable such detection.
-
-4.7) Delays and precision timing
-
-Precise timing and delays may not be possible in a virtualized system.  This
-can happen if the system is controlling physical hardware, or issues delays to
-compensate for slower I/O to and from devices.  The first issue is not solvable
-in general for a virtualized system; hardware control software can't be
-adequately virtualized without a full real-time operating system, which would
-require an RT aware virtualization platform.
-
-The second issue may cause performance problems, but this is unlikely to be a
-significant issue.  In many cases these delays may be eliminated through
-configuration or paravirtualization.
-
-4.8) Covert channels and leaks
-
-In addition to the above problems, time information will inevitably leak to the
-guest about the host in anything but a perfect implementation of virtualized
-time.  This may allow the guest to infer the presence of a hypervisor (as in a
-red-pill type detection), and it may allow information to leak between guests
-by using CPU utilization itself as a signalling channel.  Preventing such
-problems would require completely isolated virtual time which may not track
-real time any longer.  This may be useful in certain security or QA contexts,
-but in general isn't recommended for real-world deployment scenarios.
diff --git a/Documentation/virtual/kvm/vcpu-requests.rst b/Documentation/virtual/kvm/vcpu-requests.rst
deleted file mode 100644 (file)
index 5feb370..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-=================
-KVM VCPU Requests
-=================
-
-Overview
-========
-
-KVM supports an internal API enabling threads to request a VCPU thread to
-perform some activity.  For example, a thread may request a VCPU to flush
-its TLB with a VCPU request.  The API consists of the following functions::
-
-  /* Check if any requests are pending for VCPU @vcpu. */
-  bool kvm_request_pending(struct kvm_vcpu *vcpu);
-
-  /* Check if VCPU @vcpu has request @req pending. */
-  bool kvm_test_request(int req, struct kvm_vcpu *vcpu);
-
-  /* Clear request @req for VCPU @vcpu. */
-  void kvm_clear_request(int req, struct kvm_vcpu *vcpu);
-
-  /*
-   * Check if VCPU @vcpu has request @req pending. When the request is
-   * pending it will be cleared and a memory barrier, which pairs with
-   * another in kvm_make_request(), will be issued.
-   */
-  bool kvm_check_request(int req, struct kvm_vcpu *vcpu);
-
-  /*
-   * Make request @req of VCPU @vcpu. Issues a memory barrier, which pairs
-   * with another in kvm_check_request(), prior to setting the request.
-   */
-  void kvm_make_request(int req, struct kvm_vcpu *vcpu);
-
-  /* Make request @req of all VCPUs of the VM with struct kvm @kvm. */
-  bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
-
-Typically a requester wants the VCPU to perform the activity as soon
-as possible after making the request.  This means most requests
-(kvm_make_request() calls) are followed by a call to kvm_vcpu_kick(),
-and kvm_make_all_cpus_request() has the kicking of all VCPUs built
-into it.
-
-VCPU Kicks
-----------
-
-The goal of a VCPU kick is to bring a VCPU thread out of guest mode in
-order to perform some KVM maintenance.  To do so, an IPI is sent, forcing
-a guest mode exit.  However, a VCPU thread may not be in guest mode at the
-time of the kick.  Therefore, depending on the mode and state of the VCPU
-thread, there are two other actions a kick may take.  All three actions
-are listed below:
-
-1) Send an IPI.  This forces a guest mode exit.
-2) Waking a sleeping VCPU.  Sleeping VCPUs are VCPU threads outside guest
-   mode that wait on waitqueues.  Waking them removes the threads from
-   the waitqueues, allowing the threads to run again.  This behavior
-   may be suppressed, see KVM_REQUEST_NO_WAKEUP below.
-3) Nothing.  When the VCPU is not in guest mode and the VCPU thread is not
-   sleeping, then there is nothing to do.
-
-VCPU Mode
----------
-
-VCPUs have a mode state, ``vcpu->mode``, that is used to track whether the
-guest is running in guest mode or not, as well as some specific
-outside guest mode states.  The architecture may use ``vcpu->mode`` to
-ensure VCPU requests are seen by VCPUs (see "Ensuring Requests Are Seen"),
-as well as to avoid sending unnecessary IPIs (see "IPI Reduction"), and
-even to ensure IPI acknowledgements are waited upon (see "Waiting for
-Acknowledgements").  The following modes are defined:
-
-OUTSIDE_GUEST_MODE
-
-  The VCPU thread is outside guest mode.
-
-IN_GUEST_MODE
-
-  The VCPU thread is in guest mode.
-
-EXITING_GUEST_MODE
-
-  The VCPU thread is transitioning from IN_GUEST_MODE to
-  OUTSIDE_GUEST_MODE.
-
-READING_SHADOW_PAGE_TABLES
-
-  The VCPU thread is outside guest mode, but it wants the sender of
-  certain VCPU requests, namely KVM_REQ_TLB_FLUSH, to wait until the VCPU
-  thread is done reading the page tables.
-
-VCPU Request Internals
-======================
-
-VCPU requests are simply bit indices of the ``vcpu->requests`` bitmap.
-This means general bitops, like those documented in [atomic-ops]_ could
-also be used, e.g. ::
-
-  clear_bit(KVM_REQ_UNHALT & KVM_REQUEST_MASK, &vcpu->requests);
-
-However, VCPU request users should refrain from doing so, as it would
-break the abstraction.  The first 8 bits are reserved for architecture
-independent requests, all additional bits are available for architecture
-dependent requests.
-
-Architecture Independent Requests
----------------------------------
-
-KVM_REQ_TLB_FLUSH
-
-  KVM's common MMU notifier may need to flush all of a guest's TLB
-  entries, calling kvm_flush_remote_tlbs() to do so.  Architectures that
-  choose to use the common kvm_flush_remote_tlbs() implementation will
-  need to handle this VCPU request.
-
-KVM_REQ_MMU_RELOAD
-
-  When shadow page tables are used and memory slots are removed it's
-  necessary to inform each VCPU to completely refresh the tables.  This
-  request is used for that.
-
-KVM_REQ_PENDING_TIMER
-
-  This request may be made from a timer handler run on the host on behalf
-  of a VCPU.  It informs the VCPU thread to inject a timer interrupt.
-
-KVM_REQ_UNHALT
-
-  This request may be made from the KVM common function kvm_vcpu_block(),
-  which is used to emulate an instruction that causes a CPU to halt until
-  one of an architectural specific set of events and/or interrupts is
-  received (determined by checking kvm_arch_vcpu_runnable()).  When that
-  event or interrupt arrives kvm_vcpu_block() makes the request.  This is
-  in contrast to when kvm_vcpu_block() returns due to any other reason,
-  such as a pending signal, which does not indicate the VCPU's halt
-  emulation should stop, and therefore does not make the request.
-
-KVM_REQUEST_MASK
-----------------
-
-VCPU requests should be masked by KVM_REQUEST_MASK before using them with
-bitops.  This is because only the lower 8 bits are used to represent the
-request's number.  The upper bits are used as flags.  Currently only two
-flags are defined.
-
-VCPU Request Flags
-------------------
-
-KVM_REQUEST_NO_WAKEUP
-
-  This flag is applied to requests that only need immediate attention
-  from VCPUs running in guest mode.  That is, sleeping VCPUs do not need
-  to be awaken for these requests.  Sleeping VCPUs will handle the
-  requests when they are awaken later for some other reason.
-
-KVM_REQUEST_WAIT
-
-  When requests with this flag are made with kvm_make_all_cpus_request(),
-  then the caller will wait for each VCPU to acknowledge its IPI before
-  proceeding.  This flag only applies to VCPUs that would receive IPIs.
-  If, for example, the VCPU is sleeping, so no IPI is necessary, then
-  the requesting thread does not wait.  This means that this flag may be
-  safely combined with KVM_REQUEST_NO_WAKEUP.  See "Waiting for
-  Acknowledgements" for more information about requests with
-  KVM_REQUEST_WAIT.
-
-VCPU Requests with Associated State
-===================================
-
-Requesters that want the receiving VCPU to handle new state need to ensure
-the newly written state is observable to the receiving VCPU thread's CPU
-by the time it observes the request.  This means a write memory barrier
-must be inserted after writing the new state and before setting the VCPU
-request bit.  Additionally, on the receiving VCPU thread's side, a
-corresponding read barrier must be inserted after reading the request bit
-and before proceeding to read the new state associated with it.  See
-scenario 3, Message and Flag, of [lwn-mb]_ and the kernel documentation
-[memory-barriers]_.
-
-The pair of functions, kvm_check_request() and kvm_make_request(), provide
-the memory barriers, allowing this requirement to be handled internally by
-the API.
-
-Ensuring Requests Are Seen
-==========================
-
-When making requests to VCPUs, we want to avoid the receiving VCPU
-executing in guest mode for an arbitrary long time without handling the
-request.  We can be sure this won't happen as long as we ensure the VCPU
-thread checks kvm_request_pending() before entering guest mode and that a
-kick will send an IPI to force an exit from guest mode when necessary.
-Extra care must be taken to cover the period after the VCPU thread's last
-kvm_request_pending() check and before it has entered guest mode, as kick
-IPIs will only trigger guest mode exits for VCPU threads that are in guest
-mode or at least have already disabled interrupts in order to prepare to
-enter guest mode.  This means that an optimized implementation (see "IPI
-Reduction") must be certain when it's safe to not send the IPI.  One
-solution, which all architectures except s390 apply, is to:
-
-- set ``vcpu->mode`` to IN_GUEST_MODE between disabling the interrupts and
-  the last kvm_request_pending() check;
-- enable interrupts atomically when entering the guest.
-
-This solution also requires memory barriers to be placed carefully in both
-the requesting thread and the receiving VCPU.  With the memory barriers we
-can exclude the possibility of a VCPU thread observing
-!kvm_request_pending() on its last check and then not receiving an IPI for
-the next request made of it, even if the request is made immediately after
-the check.  This is done by way of the Dekker memory barrier pattern
-(scenario 10 of [lwn-mb]_).  As the Dekker pattern requires two variables,
-this solution pairs ``vcpu->mode`` with ``vcpu->requests``.  Substituting
-them into the pattern gives::
-
-  CPU1                                    CPU2
-  =================                       =================
-  local_irq_disable();
-  WRITE_ONCE(vcpu->mode, IN_GUEST_MODE);  kvm_make_request(REQ, vcpu);
-  smp_mb();                               smp_mb();
-  if (kvm_request_pending(vcpu)) {        if (READ_ONCE(vcpu->mode) ==
-                                              IN_GUEST_MODE) {
-      ...abort guest entry...                 ...send IPI...
-  }                                       }
-
-As stated above, the IPI is only useful for VCPU threads in guest mode or
-that have already disabled interrupts.  This is why this specific case of
-the Dekker pattern has been extended to disable interrupts before setting
-``vcpu->mode`` to IN_GUEST_MODE.  WRITE_ONCE() and READ_ONCE() are used to
-pedantically implement the memory barrier pattern, guaranteeing the
-compiler doesn't interfere with ``vcpu->mode``'s carefully planned
-accesses.
-
-IPI Reduction
--------------
-
-As only one IPI is needed to get a VCPU to check for any/all requests,
-then they may be coalesced.  This is easily done by having the first IPI
-sending kick also change the VCPU mode to something !IN_GUEST_MODE.  The
-transitional state, EXITING_GUEST_MODE, is used for this purpose.
-
-Waiting for Acknowledgements
-----------------------------
-
-Some requests, those with the KVM_REQUEST_WAIT flag set, require IPIs to
-be sent, and the acknowledgements to be waited upon, even when the target
-VCPU threads are in modes other than IN_GUEST_MODE.  For example, one case
-is when a target VCPU thread is in READING_SHADOW_PAGE_TABLES mode, which
-is set after disabling interrupts.  To support these cases, the
-KVM_REQUEST_WAIT flag changes the condition for sending an IPI from
-checking that the VCPU is IN_GUEST_MODE to checking that it is not
-OUTSIDE_GUEST_MODE.
-
-Request-less VCPU Kicks
------------------------
-
-As the determination of whether or not to send an IPI depends on the
-two-variable Dekker memory barrier pattern, then it's clear that
-request-less VCPU kicks are almost never correct.  Without the assurance
-that a non-IPI generating kick will still result in an action by the
-receiving VCPU, as the final kvm_request_pending() check does for
-request-accompanying kicks, then the kick may not do anything useful at
-all.  If, for instance, a request-less kick was made to a VCPU that was
-just about to set its mode to IN_GUEST_MODE, meaning no IPI is sent, then
-the VCPU thread may continue its entry without actually having done
-whatever it was the kick was meant to initiate.
-
-One exception is x86's posted interrupt mechanism.  In this case, however,
-even the request-less VCPU kick is coupled with the same
-local_irq_disable() + smp_mb() pattern described above; the ON bit
-(Outstanding Notification) in the posted interrupt descriptor takes the
-role of ``vcpu->requests``.  When sending a posted interrupt, PIR.ON is
-set before reading ``vcpu->mode``; dually, in the VCPU thread,
-vmx_sync_pir_to_irr() reads PIR after setting ``vcpu->mode`` to
-IN_GUEST_MODE.
-
-Additional Considerations
-=========================
-
-Sleeping VCPUs
---------------
-
-VCPU threads may need to consider requests before and/or after calling
-functions that may put them to sleep, e.g. kvm_vcpu_block().  Whether they
-do or not, and, if they do, which requests need consideration, is
-architecture dependent.  kvm_vcpu_block() calls kvm_arch_vcpu_runnable()
-to check if it should awaken.  One reason to do so is to provide
-architectures a function where requests may be checked if necessary.
-
-Clearing Requests
------------------
-
-Generally it only makes sense for the receiving VCPU thread to clear a
-request.  However, in some circumstances, such as when the requesting
-thread and the receiving VCPU thread are executed serially, such as when
-they are the same thread, or when they are using some form of concurrency
-control to temporarily execute synchronously, then it's possible to know
-that the request may be cleared immediately, rather than waiting for the
-receiving VCPU thread to handle the request in VCPU RUN.  The only current
-examples of this are kvm_vcpu_block() calls made by VCPUs to block
-themselves.  A possible side-effect of that call is to make the
-KVM_REQ_UNHALT request, which may then be cleared immediately when the
-VCPU returns from the call.
-
-References
-==========
-
-.. [atomic-ops] Documentation/core-api/atomic_ops.rst
-.. [memory-barriers] Documentation/memory-barriers.txt
-.. [lwn-mb] https://lwn.net/Articles/573436/
diff --git a/Documentation/virtual/paravirt_ops.rst b/Documentation/virtual/paravirt_ops.rst
deleted file mode 100644 (file)
index 6b789d2..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============
-Paravirt_ops
-============
-
-Linux provides support for different hypervisor virtualization technologies.
-Historically different binary kernels would be required in order to support
-different hypervisors, this restriction was removed with pv_ops.
-Linux pv_ops is a virtualization API which enables support for different
-hypervisors. It allows each hypervisor to override critical operations and
-allows a single kernel binary to run on all supported execution environments
-including native machine -- without any hypervisors.
-
-pv_ops provides a set of function pointers which represent operations
-corresponding to low level critical instructions and high level
-functionalities in various areas. pv-ops allows for optimizations at run
-time by enabling binary patching of the low-ops critical operations
-at boot time.
-
-pv_ops operations are classified into three categories:
-
-- simple indirect call
-   These operations correspond to high level functionality where it is
-   known that the overhead of indirect call isn't very important.
-
-- indirect call which allows optimization with binary patch
-   Usually these operations correspond to low level critical instructions. They
-   are called frequently and are performance critical. The overhead is
-   very important.
-
-- a set of macros for hand written assembly code
-   Hand written assembly codes (.S files) also need paravirtualization
-   because they include sensitive instructions or some of code paths in
-   them are very performance critical.
diff --git a/Documentation/virtual/uml/UserModeLinux-HOWTO.txt b/Documentation/virtual/uml/UserModeLinux-HOWTO.txt
deleted file mode 100644 (file)
index 87b80f5..0000000
+++ /dev/null
@@ -1,4589 +0,0 @@
-  User Mode Linux HOWTO
-  User Mode Linux Core Team
-  Mon Nov 18 14:16:16 EST 2002
-
-  This document describes the use and abuse of Jeff Dike's User Mode
-  Linux: a port of the Linux kernel as a normal Intel Linux process.
-  ______________________________________________________________________
-
-  Table of Contents
-
-  1. Introduction
-
-     1.1 How is User Mode Linux Different?
-     1.2 Why Would I Want User Mode Linux?
-
-  2. Compiling the kernel and modules
-
-     2.1 Compiling the kernel
-     2.2 Compiling and installing kernel modules
-     2.3 Compiling and installing uml_utilities
-
-  3. Running UML and logging in
-
-     3.1 Running UML
-     3.2 Logging in
-     3.3 Examples
-
-  4. UML on 2G/2G hosts
-
-     4.1 Introduction
-     4.2 The problem
-     4.3 The solution
-
-  5. Setting up serial lines and consoles
-
-     5.1 Specifying the device
-     5.2 Specifying the channel
-     5.3 Examples
-
-  6. Setting up the network
-
-     6.1 General setup
-     6.2 Userspace daemons
-     6.3 Specifying ethernet addresses
-     6.4 UML interface setup
-     6.5 Multicast
-     6.6 TUN/TAP with the uml_net helper
-     6.7 TUN/TAP with a preconfigured tap device
-     6.8 Ethertap
-     6.9 The switch daemon
-     6.10 Slip
-     6.11 Slirp
-     6.12 pcap
-     6.13 Setting up the host yourself
-
-  7. Sharing Filesystems between Virtual Machines
-
-     7.1 A warning
-     7.2 Using layered block devices
-     7.3 Note!
-     7.4 Another warning
-     7.5 uml_moo : Merging a COW file with its backing file
-
-  8. Creating filesystems
-
-     8.1 Create the filesystem file
-     8.2 Assign the file to a UML device
-     8.3 Creating and mounting the filesystem
-
-  9. Host file access
-
-     9.1 Using hostfs
-     9.2 hostfs as the root filesystem
-     9.3 Building hostfs
-
-  10. The Management Console
-     10.1 version
-     10.2 halt and reboot
-     10.3 config
-     10.4 remove
-     10.5 sysrq
-     10.6 help
-     10.7 cad
-     10.8 stop
-     10.9 go
-
-  11. Kernel debugging
-
-     11.1 Starting the kernel under gdb
-     11.2 Examining sleeping processes
-     11.3 Running ddd on UML
-     11.4 Debugging modules
-     11.5 Attaching gdb to the kernel
-     11.6 Using alternate debuggers
-
-  12. Kernel debugging examples
-
-     12.1 The case of the hung fsck
-     12.2 Episode 2: The case of the hung fsck
-
-  13. What to do when UML doesn't work
-
-     13.1 Strange compilation errors when you build from source
-     13.2 (obsolete)
-     13.3 A variety of panics and hangs with /tmp on a reiserfs  filesystem
-     13.4 The compile fails with errors about conflicting types for 'open', 'dup', and 'waitpid'
-     13.5 UML doesn't work when /tmp is an NFS filesystem
-     13.6 UML hangs on boot when compiled with gprof support
-     13.7 syslogd dies with a SIGTERM on startup
-     13.8 TUN/TAP networking doesn't work on a 2.4 host
-     13.9 You can network to the host but not to other machines on the net
-     13.10 I have no root and I want to scream
-     13.11 UML build conflict between ptrace.h and ucontext.h
-     13.12 The UML BogoMips is exactly half the host's BogoMips
-     13.13 When you run UML, it immediately segfaults
-     13.14 xterms appear, then immediately disappear
-     13.15 Any other panic, hang, or strange behavior
-
-  14. Diagnosing Problems
-
-     14.1 Case 1 : Normal kernel panics
-     14.2 Case 2 : Tracing thread panics
-     14.3 Case 3 : Tracing thread panics caused by other threads
-     14.4 Case 4 : Hangs
-
-  15. Thanks
-
-     15.1 Code and Documentation
-     15.2 Flushing out bugs
-     15.3 Buglets and clean-ups
-     15.4 Case Studies
-     15.5 Other contributions
-
-
-  ______________________________________________________________________
-
-  1.  Introduction
-
-  Welcome to User Mode Linux.  It's going to be fun.
-
-
-
-  1.1.  How is User Mode Linux Different?
-
-  Normally, the Linux Kernel talks straight to your hardware (video
-  card, keyboard, hard drives, etc), and any programs which run ask the
-  kernel to operate the hardware, like so:
-
-
-
-         +-----------+-----------+----+
-         | Process 1 | Process 2 | ...|
-         +-----------+-----------+----+
-         |       Linux Kernel         |
-         +----------------------------+
-         |         Hardware           |
-         +----------------------------+
-
-
-
-
-  The User Mode Linux Kernel is different; instead of talking to the
-  hardware, it talks to a `real' Linux kernel (called the `host kernel'
-  from now on), like any other program.  Programs can then run inside
-  User-Mode Linux as if they were running under a normal kernel, like
-  so:
-
-
-
-                     +----------------+
-                     | Process 2 | ...|
-         +-----------+----------------+
-         | Process 1 | User-Mode Linux|
-         +----------------------------+
-         |       Linux Kernel         |
-         +----------------------------+
-         |         Hardware           |
-         +----------------------------+
-
-
-
-
-
-  1.2.  Why Would I Want User Mode Linux?
-
-
-  1. If User Mode Linux crashes, your host kernel is still fine.
-
-  2. You can run a usermode kernel as a non-root user.
-
-  3. You can debug the User Mode Linux like any normal process.
-
-  4. You can run gprof (profiling) and gcov (coverage testing).
-
-  5. You can play with your kernel without breaking things.
-
-  6. You can use it as a sandbox for testing new apps.
-
-  7. You can try new development kernels safely.
-
-  8. You can run different distributions simultaneously.
-
-  9. It's extremely fun.
-
-
-
-
-
-  2.  Compiling the kernel and modules
-
-
-
-
-  2.1.  Compiling the kernel
-
-
-  Compiling the user mode kernel is just like compiling any other
-  kernel.  Let's go through the steps, using 2.4.0-prerelease (current
-  as of this writing) as an example:
-
-
-  1. Download the latest UML patch from
-
-     the download page <http://user-mode-linux.sourceforge.net/
-
-     In this example, the file is uml-patch-2.4.0-prerelease.bz2.
-
-
-  2. Download the matching kernel from your favourite kernel mirror,
-     such as:
-
-     ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2
-     <ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2>
-     .
-
-
-  3. Make a directory and unpack the kernel into it.
-
-
-
-       host%
-       mkdir ~/uml
-
-
-
-
-
-
-       host%
-       cd ~/uml
-
-
-
-
-
-
-       host%
-       tar -xzvf linux-2.4.0-prerelease.tar.bz2
-
-
-
-
-
-
-  4. Apply the patch using
-
-
-
-       host%
-       cd ~/uml/linux
-
-
-
-       host%
-       bzcat uml-patch-2.4.0-prerelease.bz2 | patch -p1
-
-
-
-
-
-
-  5. Run your favorite config; `make xconfig ARCH=um' is the most
-     convenient.  `make config ARCH=um' and 'make menuconfig ARCH=um'
-     will work as well.  The defaults will give you a useful kernel.  If
-     you want to change something, go ahead, it probably won't hurt
-     anything.
-
-
-     Note:  If the host is configured with a 2G/2G address space split
-     rather than the usual 3G/1G split, then the packaged UML binaries
-     will not run.  They will immediately segfault.  See ``UML on 2G/2G
-     hosts''  for the scoop on running UML on your system.
-
-
-
-  6. Finish with `make linux ARCH=um': the result is a file called
-     `linux' in the top directory of your source tree.
-
-  Make sure that you don't build this kernel in /usr/src/linux.  On some
-  distributions, /usr/include/asm is a link into this pool.  The user-
-  mode build changes the other end of that link, and things that include
-  <asm/anything.h> stop compiling.
-
-  The sources are also available from cvs at the project's cvs page,
-  which has directions on getting the sources. You can also browse the
-  CVS pool from there.
-
-  If you get the CVS sources, you will have to check them out into an
-  empty directory. You will then have to copy each file into the
-  corresponding directory in the appropriate kernel pool.
-
-  If you don't have the latest kernel pool, you can get the
-  corresponding user-mode sources with
-
-
-       host% cvs co -r v_2_3_x linux
-
-
-
-
-  where 'x' is the version in your pool. Note that you will not get the
-  bug fixes and enhancements that have gone into subsequent releases.
-
-
-  2.2.  Compiling and installing kernel modules
-
-  UML modules are built in the same way as the native kernel (with the
-  exception of the 'ARCH=um' that you always need for UML):
-
-
-       host% make modules ARCH=um
-
-
-
-
-  Any modules that you want to load into this kernel need to be built in
-  the user-mode pool.  Modules from the native kernel won't work.
-
-  You can install them by using ftp or something to copy them into the
-  virtual machine and dropping them into /lib/modules/`uname -r`.
-
-  You can also get the kernel build process to install them as follows:
-
-  1. with the kernel not booted, mount the root filesystem in the top
-     level of the kernel pool:
-
-
-       host% mount root_fs mnt -o loop
-
-
-
-
-
-
-  2. run
-
-
-       host%
-       make modules_install INSTALL_MOD_PATH=`pwd`/mnt ARCH=um
-
-
-
-
-
-
-  3. unmount the filesystem
-
-
-       host% umount mnt
-
-
-
-
-
-
-  4. boot the kernel on it
-
-
-  When the system is booted, you can use insmod as usual to get the
-  modules into the kernel.  A number of things have been loaded into UML
-  as modules, especially filesystems and network protocols and filters,
-  so most symbols which need to be exported probably already are.
-  However, if you do find symbols that need exporting, let  us
-  <http://user-mode-linux.sourceforge.net/>  know, and
-  they'll be "taken care of".
-
-
-
-  2.3.  Compiling and installing uml_utilities
-
-  Many features of the UML kernel require a user-space helper program,
-  so a uml_utilities package is distributed separately from the kernel
-  patch which provides these helpers. Included within this is:
-
-  o  port-helper - Used by consoles which connect to xterms or ports
-
-  o  tunctl - Configuration tool to create and delete tap devices
-
-  o  uml_net - Setuid binary for automatic tap device configuration
-
-  o  uml_switch - User-space virtual switch required for daemon
-     transport
-
-     The uml_utilities tree is compiled with:
-
-
-       host#
-       make && make install
-
-
-
-
-  Note that UML kernel patches may require a specific version of the
-  uml_utilities distribution. If you don't keep up with the mailing
-  lists, ensure that you have the latest release of uml_utilities if you
-  are experiencing problems with your UML kernel, particularly when
-  dealing with consoles or command-line switches to the helper programs
-
-
-
-
-
-
-
-
-  3.  Running UML and logging in
-
-
-
-  3.1.  Running UML
-
-  It runs on 2.2.15 or later, and all 2.4 kernels.
-
-
-  Booting UML is straightforward.  Simply run 'linux': it will try to
-  mount the file `root_fs' in the current directory.  You do not need to
-  run it as root.  If your root filesystem is not named `root_fs', then
-  you need to put a `ubd0=root_fs_whatever' switch on the linux command
-  line.
-
-
-  You will need a filesystem to boot UML from.  There are a number
-  available for download from  here  <http://user-mode-
-  linux.sourceforge.net/> .  There are also  several tools
-  <http://user-mode-linux.sourceforge.net/>  which can be
-  used to generate UML-compatible filesystem images from media.
-  The kernel will boot up and present you with a login prompt.
-
-
-  Note:  If the host is configured with a 2G/2G address space split
-  rather than the usual 3G/1G split, then the packaged UML binaries will
-  not run.  They will immediately segfault.  See ``UML on 2G/2G hosts''
-  for the scoop on running UML on your system.
-
-
-
-  3.2.  Logging in
-
-
-
-  The prepackaged filesystems have a root account with password 'root'
-  and a user account with password 'user'.  The login banner will
-  generally tell you how to log in.  So, you log in and you will find
-  yourself inside a little virtual machine. Our filesystems have a
-  variety of commands and utilities installed (and it is fairly easy to
-  add more), so you will have a lot of tools with which to poke around
-  the system.
-
-  There are a couple of other ways to log in:
-
-  o  On a virtual console
-
-
-
-     Each virtual console that is configured (i.e. the device exists in
-     /dev and /etc/inittab runs a getty on it) will come up in its own
-     xterm.  If you get tired of the xterms, read ``Setting up serial
-     lines and consoles''  to see how to attach the consoles to
-     something else, like host ptys.
-
-
-
-  o  Over the serial line
-
-
-     In the boot output, find a line that looks like:
-
-
-
-       serial line 0 assigned pty /dev/ptyp1
-
-
-
-
-  Attach your favorite terminal program to the corresponding tty.  I.e.
-  for minicom, the command would be
-
-
-       host% minicom -o -p /dev/ttyp1
-
-
-
-
-
-
-  o  Over the net
-
-
-     If the network is running, then you can telnet to the virtual
-     machine and log in to it.  See ``Setting up the network''  to learn
-     about setting up a virtual network.
-
-  When you're done using it, run halt, and the kernel will bring itself
-  down and the process will exit.
-
-
-  3.3.  Examples
-
-  Here are some examples of UML in action:
-
-  o  A login session <http://user-mode-linux.sourceforge.net/login.html>
-
-  o  A virtual network <http://user-mode-linux.sourceforge.net/net.html>
-
-
-
-
-
-
-
-  4.  UML on 2G/2G hosts
-
-
-
-
-  4.1.  Introduction
-
-
-  Most Linux machines are configured so that the kernel occupies the
-  upper 1G (0xc0000000 - 0xffffffff) of the 4G address space and
-  processes use the lower 3G (0x00000000 - 0xbfffffff).  However, some
-  machine are configured with a 2G/2G split, with the kernel occupying
-  the upper 2G (0x80000000 - 0xffffffff) and processes using the lower
-  2G (0x00000000 - 0x7fffffff).
-
-
-
-
-  4.2.  The problem
-
-
-  The prebuilt UML binaries on this site will not run on 2G/2G hosts
-  because UML occupies the upper .5G of the 3G process address space
-  (0xa0000000 - 0xbfffffff).  Obviously, on 2G/2G hosts, this is right
-  in the middle of the kernel address space, so UML won't even load - it
-  will immediately segfault.
-
-
-
-
-  4.3.  The solution
-
-
-  The fix for this is to rebuild UML from source after enabling
-  CONFIG_HOST_2G_2G (under 'General Setup').  This will cause UML to
-  load itself in the top .5G of that smaller process address space,
-  where it will run fine.  See ``Compiling the kernel and modules''  if
-  you need help building UML from source.
-
-
-
-
-
-
-
-
-
-
-  5.  Setting up serial lines and consoles
-
-
-  It is possible to attach UML serial lines and consoles to many types
-  of host I/O channels by specifying them on the command line.
-
-
-  You can attach them to host ptys, ttys, file descriptors, and ports.
-  This allows you to do things like
-
-  o  have a UML console appear on an unused host console,
-
-  o  hook two virtual machines together by having one attach to a pty
-     and having the other attach to the corresponding tty
-
-  o  make a virtual machine accessible from the net by attaching a
-     console to a port on the host.
-
-
-  The general format of the command line option is device=channel.
-
-
-
-  5.1.  Specifying the device
-
-  Devices are specified with "con" or "ssl" (console or serial line,
-  respectively), optionally with a device number if you are talking
-  about a specific device.
-
-
-  Using just "con" or "ssl" describes all of the consoles or serial
-  lines.  If you want to talk about console #3 or serial line #10, they
-  would be "con3" and "ssl10", respectively.
-
-
-  A specific device name will override a less general "con=" or "ssl=".
-  So, for example, you can assign a pty to each of the serial lines
-  except for the first two like this:
-
-
-        ssl=pty ssl0=tty:/dev/tty0 ssl1=tty:/dev/tty1
-
-
-
-
-  The specificity of the device name is all that matters; order on the
-  command line is irrelevant.
-
-
-
-  5.2.  Specifying the channel
-
-  There are a number of different types of channels to attach a UML
-  device to, each with a different way of specifying exactly what to
-  attach to.
-
-  o  pseudo-terminals - device=pty pts terminals - device=pts
-
-
-     This will cause UML to allocate a free host pseudo-terminal for the
-     device.  The terminal that it got will be announced in the boot
-     log.  You access it by attaching a terminal program to the
-     corresponding tty:
-
-  o  screen /dev/pts/n
-
-  o  screen /dev/ttyxx
-
-  o  minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
-     devices
-
-  o  kermit - start it up, 'open' the device, then 'connect'
-
-
-
-
-
-  o  terminals - device=tty:tty device file
-
-
-     This will make UML attach the device to the specified tty (i.e
-
-
-        con1=tty:/dev/tty3
-
-
-
-
-  will attach UML's console 1 to the host's /dev/tty3).  If the tty that
-  you specify is the slave end of a tty/pty pair, something else must
-  have already opened the corresponding pty in order for this to work.
-
-
-
-
-
-  o  xterms - device=xterm
-
-
-     UML will run an xterm and the device will be attached to it.
-
-
-
-
-
-  o  Port - device=port:port number
-
-
-     This will attach the UML devices to the specified host port.
-     Attaching console 1 to the host's port 9000 would be done like
-     this:
-
-
-        con1=port:9000
-
-
-
-
-  Attaching all the serial lines to that port would be done similarly:
-
-
-        ssl=port:9000
-
-
-
-
-  You access these devices by telnetting to that port.  Each active tel-
-  net session gets a different device.  If there are more telnets to a
-  port than UML devices attached to it, then the extra telnet sessions
-  will block until an existing telnet detaches, or until another device
-  becomes active (i.e. by being activated in /etc/inittab).
-
-  This channel has the advantage that you can both attach multiple UML
-  devices to it and know how to access them without reading the UML boot
-  log.  It is also unique in allowing access to a UML from remote
-  machines without requiring that the UML be networked.  This could be
-  useful in allowing public access to UMLs because they would be
-  accessible from the net, but wouldn't need any kind of network
-  filtering or access control because they would have no network access.
-
-
-  If you attach the main console to a portal, then the UML boot will
-  appear to hang.  In reality, it's waiting for a telnet to connect, at
-  which point the boot will proceed.
-
-
-
-
-
-  o  already-existing file descriptors - device=file descriptor
-
-
-     If you set up a file descriptor on the UML command line, you can
-     attach a UML device to it.  This is most commonly used to put the
-     main console back on stdin and stdout after assigning all the other
-     consoles to something else:
-
-
-        con0=fd:0,fd:1 con=pts
-
-
-
-
-
-
-
-
-  o  Nothing - device=null
-
-
-     This allows the device to be opened, in contrast to 'none', but
-     reads will block, and writes will succeed and the data will be
-     thrown out.
-
-
-
-
-
-  o  None - device=none
-
-
-     This causes the device to disappear.
-
-
-
-  You can also specify different input and output channels for a device
-  by putting a comma between them:
-
-
-        ssl3=tty:/dev/tty2,xterm
-
-
-
-
-  will cause serial line 3 to accept input on the host's /dev/tty2 and
-  display output on an xterm.  That's a silly example - the most common
-  use of this syntax is to reattach the main console to stdin and stdout
-  as shown above.
-
-
-  If you decide to move the main console away from stdin/stdout, the
-  initial boot output will appear in the terminal that you're running
-  UML in.  However, once the console driver has been officially
-  initialized, then the boot output will start appearing wherever you
-  specified that console 0 should be.  That device will receive all
-  subsequent output.
-
-
-
-  5.3.  Examples
-
-  There are a number of interesting things you can do with this
-  capability.
-
-
-  First, this is how you get rid of those bleeding console xterms by
-  attaching them to host ptys:
-
-
-        con=pty con0=fd:0,fd:1
-
-
-
-
-  This will make a UML console take over an unused host virtual console,
-  so that when you switch to it, you will see the UML login prompt
-  rather than the host login prompt:
-
-
-        con1=tty:/dev/tty6
-
-
-
-
-  You can attach two virtual machines together with what amounts to a
-  serial line as follows:
-
-  Run one UML with a serial line attached to a pty -
-
-
-        ssl1=pty
-
-
-
-
-  Look at the boot log to see what pty it got (this example will assume
-  that it got /dev/ptyp1).
-
-  Boot the other UML with a serial line attached to the corresponding
-  tty -
-
-
-        ssl1=tty:/dev/ttyp1
-
-
-
-
-  Log in, make sure that it has no getty on that serial line, attach a
-  terminal program like minicom to it, and you should see the login
-  prompt of the other virtual machine.
-
-
-  6.  Setting up the network
-
-
-
-  This page describes how to set up the various transports and to
-  provide a UML instance with network access to the host, other machines
-  on the local net, and the rest of the net.
-
-
-  As of 2.4.5, UML networking has been completely redone to make it much
-  easier to set up, fix bugs, and add new features.
-
-
-  There is a new helper, uml_net, which does the host setup that
-  requires root privileges.
-
-
-  There are currently five transport types available for a UML virtual
-  machine to exchange packets with other hosts:
-
-  o  ethertap
-
-  o  TUN/TAP
-
-  o  Multicast
-
-  o  a switch daemon
-
-  o  slip
-
-  o  slirp
-
-  o  pcap
-
-     The TUN/TAP, ethertap, slip, and slirp transports allow a UML
-     instance to exchange packets with the host.  They may be directed
-     to the host or the host may just act as a router to provide access
-     to other physical or virtual machines.
-
-
-  The pcap transport is a synthetic read-only interface, using the
-  libpcap binary to collect packets from interfaces on the host and
-  filter them.  This is useful for building preconfigured traffic
-  monitors or sniffers.
-
-
-  The daemon and multicast transports provide a completely virtual
-  network to other virtual machines.  This network is completely
-  disconnected from the physical network unless one of the virtual
-  machines on it is acting as a gateway.
-
-
-  With so many host transports, which one should you use?  Here's when
-  you should use each one:
-
-  o  ethertap - if you want access to the host networking and it is
-     running 2.2
-
-  o  TUN/TAP - if you want access to the host networking and it is
-     running 2.4.  Also, the TUN/TAP transport is able to use a
-     preconfigured device, allowing it to avoid using the setuid uml_net
-     helper, which is a security advantage.
-
-  o  Multicast - if you want a purely virtual network and you don't want
-     to set up anything but the UML
-
-  o  a switch daemon - if you want a purely virtual network and you
-     don't mind running the daemon in order to get somewhat better
-     performance
-
-  o  slip - there is no particular reason to run the slip backend unless
-     ethertap and TUN/TAP are just not available for some reason
-
-  o  slirp - if you don't have root access on the host to setup
-     networking, or if you don't want to allocate an IP to your UML
-
-  o  pcap - not much use for actual network connectivity, but great for
-     monitoring traffic on the host
-
-     Ethertap is available on 2.4 and works fine.  TUN/TAP is preferred
-     to it because it has better performance and ethertap is officially
-     considered obsolete in 2.4.  Also, the root helper only needs to
-     run occasionally for TUN/TAP, rather than handling every packet, as
-     it does with ethertap.  This is a slight security advantage since
-     it provides fewer opportunities for a nasty UML user to somehow
-     exploit the helper's root privileges.
-
-
-  6.1.  General setup
-
-  First, you must have the virtual network enabled in your UML.  If are
-  running a prebuilt kernel from this site, everything is already
-  enabled.  If you build the kernel yourself, under the "Network device
-  support" menu, enable "Network device support", and then the three
-  transports.
-
-
-  The next step is to provide a network device to the virtual machine.
-  This is done by describing it on the kernel command line.
-
-  The general format is
-
-
-       eth <n> = <transport> , <transport args>
-
-
-
-
-  For example, a virtual ethernet device may be attached to a host
-  ethertap device as follows:
-
-
-       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
-
-
-
-
-  This sets up eth0 inside the virtual machine to attach itself to the
-  host /dev/tap0, assigns it an ethernet address, and assigns the host
-  tap0 interface an IP address.
-
-
-
-  Note that the IP address you assign to the host end of the tap device
-  must be different than the IP you assign to the eth device inside UML.
-  If you are short on IPs and don't want to consume two per UML, then
-  you can reuse the host's eth IP address for the host ends of the tap
-  devices.  Internally, the UMLs must still get unique IPs for their eth
-  devices.  You can also give the UMLs non-routable IPs (192.168.x.x or
-  10.x.x.x) and have the host masquerade them.  This will let outgoing
-  connections work, but incoming connections won't without more work,
-  such as port forwarding from the host.
-  Also note that when you configure the host side of an interface, it is
-  only acting as a gateway.  It will respond to pings sent to it
-  locally, but is not useful to do that since it's a host interface.
-  You are not talking to the UML when you ping that interface and get a
-  response.
-
-
-  You can also add devices to a UML and remove them at runtime.  See the
-  ``The Management Console''  page for details.
-
-
-  The sections below describe this in more detail.
-
-
-  Once you've decided how you're going to set up the devices, you boot
-  UML, log in, configure the UML side of the devices, and set up routes
-  to the outside world.  At that point, you will be able to talk to any
-  other machines, physical or virtual, on the net.
-
-
-  If ifconfig inside UML fails and the network refuses to come up, run
-  tell you what went wrong.
-
-
-
-  6.2.  Userspace daemons
-
-  You will likely need the setuid helper, or the switch daemon, or both.
-  They are both installed with the RPM and deb, so if you've installed
-  either, you can skip the rest of this section.
-
-
-  If not, then you need to check them out of CVS, build them, and
-  install them.  The helper is uml_net, in CVS /tools/uml_net, and the
-  daemon is uml_switch, in CVS /tools/uml_router.  They are both built
-  with a plain 'make'.  Both need to be installed in a directory that's
-  in your path - /usr/bin is recommend.  On top of that, uml_net needs
-  to be setuid root.
-
-
-
-  6.3.  Specifying ethernet addresses
-
-  Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
-  allow you to specify hardware addresses for the virtual ethernet
-  devices.  This is generally not necessary.  If you don't have a
-  specific reason to do it, you probably shouldn't.  If one is not
-  specified on the command line, the driver will assign one based on the
-  device IP address.  It will provide the address fe:fd:nn:nn:nn:nn
-  where nn.nn.nn.nn is the device IP address.  This is nearly always
-  sufficient to guarantee a unique hardware address for the device.  A
-  couple of exceptions are:
-
-  o  Another set of virtual ethernet devices are on the same network and
-     they are assigned hardware addresses using a different scheme which
-     may conflict with the UML IP address-based scheme
-
-  o  You aren't going to use the device for IP networking, so you don't
-     assign the device an IP address
-
-     If you let the driver provide the hardware address, you should make
-     sure that the device IP address is known before the interface is
-     brought up.  So, inside UML, this will guarantee that:
-
-
-
-  UML#
-  ifconfig eth0 192.168.0.250 up
-
-
-
-
-  If you decide to assign the hardware address yourself, make sure that
-  the first byte of the address is even.  Addresses with an odd first
-  byte are broadcast addresses, which you don't want assigned to a
-  device.
-
-
-
-  6.4.  UML interface setup
-
-  Once the network devices have been described on the command line, you
-  should boot UML and log in.
-
-
-  The first thing to do is bring the interface up:
-
-
-       UML# ifconfig ethn ip-address up
-
-
-
-
-  You should be able to ping the host at this point.
-
-
-  To reach the rest of the world, you should set a default route to the
-  host:
-
-
-       UML# route add default gw host ip
-
-
-
-
-  Again, with host ip of 192.168.0.4:
-
-
-       UML# route add default gw 192.168.0.4
-
-
-
-
-  This page used to recommend setting a network route to your local net.
-  This is wrong, because it will cause UML to try to figure out hardware
-  addresses of the local machines by arping on the interface to the
-  host.  Since that interface is basically a single strand of ethernet
-  with two nodes on it (UML and the host) and arp requests don't cross
-  networks, they will fail to elicit any responses.  So, what you want
-  is for UML to just blindly throw all packets at the host and let it
-  figure out what to do with them, which is what leaving out the network
-  route and adding the default route does.
-
-
-  Note: If you can't communicate with other hosts on your physical
-  ethernet, it's probably because of a network route that's
-  automatically set up.  If you run 'route -n' and see a route that
-  looks like this:
-
-
-
-
-  Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
-  192.168.0.0     0.0.0.0         255.255.255.0   U     0      0      0   eth0
-
-
-
-
-  with a mask that's not 255.255.255.255, then replace it with a route
-  to your host:
-
-
-       UML#
-       route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0
-
-
-
-
-
-
-       UML#
-       route add -host 192.168.0.4 dev eth0
-
-
-
-
-  This, plus the default route to the host, will allow UML to exchange
-  packets with any machine on your ethernet.
-
-
-
-  6.5.  Multicast
-
-  The simplest way to set up a virtual network between multiple UMLs is
-  to use the mcast transport.  This was written by Harald Welte and is
-  present in UML version 2.4.5-5um and later.  Your system must have
-  multicast enabled in the kernel and there must be a multicast-capable
-  network device on the host.  Normally, this is eth0, but if there is
-  no ethernet card on the host, then you will likely get strange error
-  messages when you bring the device up inside UML.
-
-
-  To use it, run two UMLs with
-
-
-        eth0=mcast
-
-
-
-
-  on their command lines.  Log in, configure the ethernet device in each
-  machine with different IP addresses:
-
-
-       UML1# ifconfig eth0 192.168.0.254
-
-
-
-
-
-
-       UML2# ifconfig eth0 192.168.0.253
-
-
-
-
-  and they should be able to talk to each other.
-
-  The full set of command line options for this transport are
-
-
-
-       ethn=mcast,ethernet address,multicast
-       address,multicast port,ttl
-
-
-
-
-  Harald's original README is here <http://user-mode-linux.source-
-  forge.net/>  and explains these in detail, as well as
-  some other issues.
-
-  There is also a related point-to-point only "ucast" transport.
-  This is useful when your network does not support multicast, and
-  all network connections are simple point to point links.
-
-  The full set of command line options for this transport are
-
-
-       ethn=ucast,ethernet address,remote address,listen port,remote port
-
-
-
-
-  6.6.  TUN/TAP with the uml_net helper
-
-  TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
-  host.  The TUN/TAP backend has been in UML since 2.4.9-3um.
-
-
-  The easiest way to get up and running is to let the setuid uml_net
-  helper do the host setup for you.  This involves insmod-ing the tun.o
-  module if necessary, configuring the device, and setting up IP
-  forwarding, routing, and proxy arp.  If you are new to UML networking,
-  do this first.  If you're concerned about the security implications of
-  the setuid helper, use it to get up and running, then read the next
-  section to see how to have UML use a preconfigured tap device, which
-  avoids the use of uml_net.
-
-
-  If you specify an IP address for the host side of the device, the
-  uml_net helper will do all necessary setup on the host - the only
-  requirement is that TUN/TAP be available, either built in to the host
-  kernel or as the tun.o module.
-
-  The format of the command line switch to attach a device to a TUN/TAP
-  device is
-
-
-       eth <n> =tuntap,,, <IP address>
-
-
-
-
-  For example, this argument will attach the UML's eth0 to the next
-  available tap device and assign an ethernet address to it based on its
-  IP address
-
-
-       eth0=tuntap,,,192.168.0.254
-
-
-
-
-
-
-  Note that the IP address that must be used for the eth device inside
-  UML is fixed by the routing and proxy arp that is set up on the
-  TUN/TAP device on the host.  You can use a different one, but it won't
-  work because reply packets won't reach the UML.  This is a feature.
-  It prevents a nasty UML user from doing things like setting the UML IP
-  to the same as the network's nameserver or mail server.
-
-
-  There are a couple potential problems with running the TUN/TAP
-  transport on a 2.4 host kernel
-
-  o  TUN/TAP seems not to work on 2.4.3 and earlier.  Upgrade the host
-     kernel or use the ethertap transport.
-
-  o  With an upgraded kernel, TUN/TAP may fail with
-
-
-       File descriptor in bad state
-
-
-
-
-  This is due to a header mismatch between the upgraded kernel and the
-  kernel that was originally installed on the machine.  The fix is to
-  make sure that /usr/src/linux points to the headers for the running
-  kernel.
-
-  These were pointed out by Tim Robinson <timro at trkr dot net> in
-  <http://www.geocrawler.com/> name="this uml-
-  user post"> .
-
-
-
-  6.7.  TUN/TAP with a preconfigured tap device
-
-  If you prefer not to have UML use uml_net (which is somewhat
-  insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
-  beforehand.  The setup needs to be done as root, but once that's done,
-  there is no need for root assistance.  Setting up the device is done
-  as follows:
-
-  o  Create the device with tunctl (available from the UML utilities
-     tarball)
-
-
-
-
-       host#  tunctl -u uid
-
-
-
-
-  where uid is the user id or username that UML will be run as.  This
-  will tell you what device was created.
-
-  o  Configure the device IP (change IP addresses and device name to
-     suit)
-
-
-
-
-       host#  ifconfig tap0 192.168.0.254 up
-
-
-
-
-
-  o  Set up routing and arping if desired - this is my recipe, there are
-     other ways of doing the same thing
-
-
-       host#
-       bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
-
-       host#
-       route add -host 192.168.0.253 dev tap0
-
-
-
-
-
-
-       host#
-       bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp'
-
-
-
-
-
-
-       host#
-       arp -Ds 192.168.0.253 eth0 pub
-
-
-
-
-  Note that this must be done every time the host boots - this configu-
-  ration is not stored across host reboots.  So, it's probably a good
-  idea to stick it in an rc file.  An even better idea would be a little
-  utility which reads the information from a config file and sets up
-  devices at boot time.
-
-  o  Rather than using up two IPs and ARPing for one of them, you can
-     also provide direct access to your LAN by the UML by using a
-     bridge.
-
-
-       host#
-       brctl addbr br0
-
-
-
-
-
-
-       host#
-       ifconfig eth0 0.0.0.0 promisc up
-
-
-
-
-
-
-       host#
-       ifconfig tap0 0.0.0.0 promisc up
-
-
-
-
-
-
-       host#
-       ifconfig br0 192.168.0.1 netmask 255.255.255.0 up
-
-
-
-
-
-
-
-  host#
-  brctl stp br0 off
-
-
-
-
-
-
-       host#
-       brctl setfd br0 1
-
-
-
-
-
-
-       host#
-       brctl sethello br0 1
-
-
-
-
-
-
-       host#
-       brctl addif br0 eth0
-
-
-
-
-
-
-       host#
-       brctl addif br0 tap0
-
-
-
-
-  Note that 'br0' should be setup using ifconfig with the existing IP
-  address of eth0, as eth0 no longer has its own IP.
-
-  o
-
-
-     Also, the /dev/net/tun device must be writable by the user running
-     UML in order for the UML to use the device that's been configured
-     for it.  The simplest thing to do is
-
-
-       host#  chmod 666 /dev/net/tun
-
-
-
-
-  Making it world-writable looks bad, but it seems not to be
-  exploitable as a security hole.  However, it does allow anyone to cre-
-  ate useless tap devices (useless because they can't configure them),
-  which is a DOS attack.  A somewhat more secure alternative would to be
-  to create a group containing all the users who have preconfigured tap
-  devices and chgrp /dev/net/tun to that group with mode 664 or 660.
-
-
-  o  Once the device is set up, run UML with 'eth0=tuntap,device name'
-     (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
-     mconsole config command).
-
-  o  Bring the eth device up in UML and you're in business.
-
-     If you don't want that tap device any more, you can make it non-
-     persistent with
-
-
-       host#  tunctl -d tap device
-
-
-
-
-  Finally, tunctl has a -b (for brief mode) switch which causes it to
-  output only the name of the tap device it created.  This makes it
-  suitable for capture by a script:
-
-
-       host#  TAP=`tunctl -u 1000 -b`
-
-
-
-
-
-
-  6.8.  Ethertap
-
-  Ethertap is the general mechanism on 2.2 for userspace processes to
-  exchange packets with the kernel.
-
-
-
-  To use this transport, you need to describe the virtual network device
-  on the UML command line.  The general format for this is
-
-
-       eth <n> =ethertap, <device> , <ethernet address> , <tap IP address>
-
-
-
-
-  So, the previous example
-
-
-       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
-
-
-
-
-  attaches the UML eth0 device to the host /dev/tap0, assigns it the
-  ethernet address fe:fd:0:0:0:1, and assigns the IP address
-  192.168.0.254 to the tap device.
-
-
-
-  The tap device is mandatory, but the others are optional.  If the
-  ethernet address is omitted, one will be assigned to it.
-
-
-  The presence of the tap IP address will cause the helper to run and do
-  whatever host setup is needed to allow the virtual machine to
-  communicate with the outside world.  If you're not sure you know what
-  you're doing, this is the way to go.
-
-
-  If it is absent, then you must configure the tap device and whatever
-  arping and routing you will need on the host.  However, even in this
-  case, the uml_net helper still needs to be in your path and it must be
-  setuid root if you're not running UML as root.  This is because the
-  tap device doesn't support SIGIO, which UML needs in order to use
-  something as a source of input.  So, the helper is used as a
-  convenient asynchronous IO thread.
-
-  If you're using the uml_net helper, you can ignore the following host
-  setup - uml_net will do it for you.  You just need to make sure you
-  have ethertap available, either built in to the host kernel or
-  available as a module.
-
-
-  If you want to set things up yourself, you need to make sure that the
-  appropriate /dev entry exists.  If it doesn't, become root and create
-  it as follows:
-
-
-       mknod /dev/tap <minor>  c 36  <minor>  + 16
-
-
-
-
-  For example, this is how to create /dev/tap0:
-
-
-       mknod /dev/tap0 c 36 0 + 16
-
-
-
-
-  You also need to make sure that the host kernel has ethertap support.
-  If ethertap is enabled as a module, you apparently need to insmod
-  ethertap once for each ethertap device you want to enable.  So,
-
-
-       host#
-       insmod ethertap
-
-
-
-
-  will give you the tap0 interface.  To get the tap1 interface, you need
-  to run
-
-
-       host#
-       insmod ethertap unit=1 -o ethertap1
-
-
-
-
-
-
-
-  6.9.  The switch daemon
-
-  Note: This is the daemon formerly known as uml_router, but which was
-  renamed so the network weenies of the world would stop growling at me.
-
-
-  The switch daemon, uml_switch, provides a mechanism for creating a
-  totally virtual network.  By default, it provides no connection to the
-  host network (but see -tap, below).
-
-
-  The first thing you need to do is run the daemon.  Running it with no
-  arguments will make it listen on a default pair of unix domain
-  sockets.
-
-
-  If you want it to listen on a different pair of sockets, use
-
-
-        -unix control socket data socket
-
-
-
-
-
-  If you want it to act as a hub rather than a switch, use
-
-
-        -hub
-
-
-
-
-
-  If you want the switch to be connected to host networking (allowing
-  the umls to get access to the outside world through the host), use
-
-
-        -tap tap0
-
-
-
-
-
-  Note that the tap device must be preconfigured (see "TUN/TAP with a
-  preconfigured tap device", above).  If you're using a different tap
-  device than tap0, specify that instead of tap0.
-
-
-  uml_switch can be backgrounded as follows
-
-
-       host%
-       uml_switch [ options ] < /dev/null > /dev/null
-
-
-
-
-  The reason it doesn't background by default is that it listens to
-  stdin for EOF.  When it sees that, it exits.
-
-
-  The general format of the kernel command line switch is
-
-
-
-       ethn=daemon,ethernet address,socket
-       type,control socket,data socket
-
-
-
-
-  You can leave off everything except the 'daemon'.  You only need to
-  specify the ethernet address if the one that will be assigned to it
-  isn't acceptable for some reason.  The rest of the arguments describe
-  how to communicate with the daemon.  You should only specify them if
-  you told the daemon to use different sockets than the default.  So, if
-  you ran the daemon with no arguments, running the UML on the same
-  machine with
-       eth0=daemon
-
-
-
-
-  will cause the eth0 driver to attach itself to the daemon correctly.
-
-
-
-  6.10.  Slip
-
-  Slip is another, less general, mechanism for a process to communicate
-  with the host networking.  In contrast to the ethertap interface,
-  which exchanges ethernet frames with the host and can be used to
-  transport any higher-level protocol, it can only be used to transport
-  IP.
-
-
-  The general format of the command line switch is
-
-
-
-       ethn=slip,slip IP
-
-
-
-
-  The slip IP argument is the IP address that will be assigned to the
-  host end of the slip device.  If it is specified, the helper will run
-  and will set up the host so that the virtual machine can reach it and
-  the rest of the network.
-
-
-  There are some oddities with this interface that you should be aware
-  of.  You should only specify one slip device on a given virtual
-  machine, and its name inside UML will be 'umn', not 'eth0' or whatever
-  you specified on the command line.  These problems will be fixed at
-  some point.
-
-
-
-  6.11.  Slirp
-
-  slirp uses an external program, usually /usr/bin/slirp, to provide IP
-  only networking connectivity through the host. This is similar to IP
-  masquerading with a firewall, although the translation is performed in
-  user-space, rather than by the kernel.  As slirp does not set up any
-  interfaces on the host, or changes routing, slirp does not require
-  root access or setuid binaries on the host.
-
-
-  The general format of the command line switch for slirp is:
-
-
-
-       ethn=slirp,ethernet address,slirp path
-
-
-
-
-  The ethernet address is optional, as UML will set up the interface
-  with an ethernet address based upon the initial IP address of the
-  interface.  The slirp path is generally /usr/bin/slirp, although it
-  will depend on distribution.
-
-
-  The slirp program can have a number of options passed to the command
-  line and we can't add them to the UML command line, as they will be
-  parsed incorrectly.  Instead, a wrapper shell script can be written or
-  the options inserted into the  /.slirprc file.  More information on
-  all of the slirp options can be found in its man pages.
-
-
-  The eth0 interface on UML should be set up with the IP 10.2.0.15,
-  although you can use anything as long as it is not used by a network
-  you will be connecting to. The default route on UML should be set to
-  use
-
-
-       UML#
-       route add default dev eth0
-
-
-
-
-  slirp provides a number of useful IP addresses which can be used by
-  UML, such as 10.0.2.3 which is an alias for the DNS server specified
-  in /etc/resolv.conf on the host or the IP given in the 'dns' option
-  for slirp.
-
-
-  Even with a baudrate setting higher than 115200, the slirp connection
-  is limited to 115200. If you need it to go faster, the slirp binary
-  needs to be compiled with FULL_BOLT defined in config.h.
-
-
-
-  6.12.  pcap
-
-  The pcap transport is attached to a UML ethernet device on the command
-  line or with uml_mconsole with the following syntax:
-
-
-
-       ethn=pcap,host interface,filter
-       expression,option1,option2
-
-
-
-
-  The expression and options are optional.
-
-
-  The interface is whatever network device on the host you want to
-  sniff.  The expression is a pcap filter expression, which is also what
-  tcpdump uses, so if you know how to specify tcpdump filters, you will
-  use the same expressions here.  The options are up to two of
-  'promisc', control whether pcap puts the host interface into
-  promiscuous mode. 'optimize' and 'nooptimize' control whether the pcap
-  expression optimizer is used.
-
-
-  Example:
-
-
-
-       eth0=pcap,eth0,tcp
-
-       eth1=pcap,eth0,!tcp
-
-
-
-  will cause the UML eth0 to emit all tcp packets on the host eth0 and
-  the UML eth1 to emit all non-tcp packets on the host eth0.
-
-
-
-  6.13.  Setting up the host yourself
-
-  If you don't specify an address for the host side of the ethertap or
-  slip device, UML won't do any setup on the host.  So this is what is
-  needed to get things working (the examples use a host-side IP of
-  192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
-  own network):
-
-  o  The device needs to be configured with its IP address.  Tap devices
-     are also configured with an mtu of 1484.  Slip devices are
-     configured with a point-to-point address pointing at the UML ip
-     address.
-
-
-       host#  ifconfig tap0 arp mtu 1484 192.168.0.251 up
-
-
-
-
-
-
-       host#
-       ifconfig sl0 192.168.0.251 pointopoint 192.168.0.250 up
-
-
-
-
-
-  o  If a tap device is being set up, a route is set to the UML IP.
-
-
-       UML# route add -host 192.168.0.250 gw 192.168.0.251
-
-
-
-
-
-  o  To allow other hosts on your network to see the virtual machine,
-     proxy arp is set up for it.
-
-
-       host#  arp -Ds 192.168.0.250 eth0 pub
-
-
-
-
-
-  o  Finally, the host is set up to route packets.
-
-
-       host#  echo 1 > /proc/sys/net/ipv4/ip_forward
-
-
-
-
-
-
-
-
-
-
-  7.  Sharing Filesystems between Virtual Machines
-
-
-
-
-  7.1.  A warning
-
-  Don't attempt to share filesystems simply by booting two UMLs from the
-  same file.  That's the same thing as booting two physical machines
-  from a shared disk.  It will result in filesystem corruption.
-
-
-
-  7.2.  Using layered block devices
-
-  The way to share a filesystem between two virtual machines is to use
-  the copy-on-write (COW) layering capability of the ubd block driver.
-  As of 2.4.6-2um, the driver supports layering a read-write private
-  device over a read-only shared device.  A machine's writes are stored
-  in the private device, while reads come from either device - the
-  private one if the requested block is valid in it, the shared one if
-  not.  Using this scheme, the majority of data which is unchanged is
-  shared between an arbitrary number of virtual machines, each of which
-  has a much smaller file containing the changes that it has made.  With
-  a large number of UMLs booting from a large root filesystem, this
-  leads to a huge disk space saving.  It will also help performance,
-  since the host will be able to cache the shared data using a much
-  smaller amount of memory, so UML disk requests will be served from the
-  host's memory rather than its disks.
-
-
-
-
-  To add a copy-on-write layer to an existing block device file, simply
-  add the name of the COW file to the appropriate ubd switch:
-
-
-        ubd0=root_fs_cow,root_fs_debian_22
-
-
-
-
-  where 'root_fs_cow' is the private COW file and 'root_fs_debian_22' is
-  the existing shared filesystem.  The COW file need not exist.  If it
-  doesn't, the driver will create and initialize it.  Once the COW file
-  has been initialized, it can be used on its own on the command line:
-
-
-        ubd0=root_fs_cow
-
-
-
-
-  The name of the backing file is stored in the COW file header, so it
-  would be redundant to continue specifying it on the command line.
-
-
-
-  7.3.  Note!
-
-  When checking the size of the COW file in order to see the gobs of
-  space that you're saving, make sure you use 'ls -ls' to see the actual
-  disk consumption rather than the length of the file.  The COW file is
-  sparse, so the length will be very different from the disk usage.
-  Here is a 'ls -l' of a COW file and backing file from one boot and
-  shutdown:
-       host% ls -l cow.debian debian2.2
-       -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
-       -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
-
-
-
-
-  Doesn't look like much saved space, does it?  Well, here's 'ls -ls':
-
-
-       host% ls -ls cow.debian debian2.2
-          880 -rw-r--r--    1 jdike    jdike    492504064 Aug  6 21:16 cow.debian
-       525832 -rwxrw-rw-    1 jdike    jdike    537919488 Aug  6 20:42 debian2.2
-
-
-
-
-  Now, you can see that the COW file has less than a meg of disk, rather
-  than 492 meg.
-
-
-
-  7.4.  Another warning
-
-  Once a filesystem is being used as a readonly backing file for a COW
-  file, do not boot directly from it or modify it in any way.  Doing so
-  will invalidate any COW files that are using it.  The mtime and size
-  of the backing file are stored in the COW file header at its creation,
-  and they must continue to match.  If they don't, the driver will
-  refuse to use the COW file.
-
-
-
-
-  If you attempt to evade this restriction by changing either the
-  backing file or the COW header by hand, you will get a corrupted
-  filesystem.
-
-
-
-
-  Among other things, this means that upgrading the distribution in a
-  backing file and expecting that all of the COW files using it will see
-  the upgrade will not work.
-
-
-
-
-  7.5.  uml_moo : Merging a COW file with its backing file
-
-  Depending on how you use UML and COW devices, it may be advisable to
-  merge the changes in the COW file into the backing file every once in
-  a while.
-
-
-
-
-  The utility that does this is uml_moo.  Its usage is
-
-
-       host% uml_moo COW file new backing file
-
-
-
-
-  There's no need to specify the backing file since that information is
-  already in the COW file header.  If you're paranoid, boot the new
-  merged file, and if you're happy with it, move it over the old backing
-  file.
-
-
-
-
-  uml_moo creates a new backing file by default as a safety measure.  It
-  also has a destructive merge option which will merge the COW file
-  directly into its current backing file.  This is really only usable
-  when the backing file only has one COW file associated with it.  If
-  there are multiple COWs associated with a backing file, a -d merge of
-  one of them will invalidate all of the others.  However, it is
-  convenient if you're short of disk space, and it should also be
-  noticeably faster than a non-destructive merge.
-
-
-
-
-  uml_moo is installed with the UML deb and RPM.  If you didn't install
-  UML from one of those packages, you can also get it from the UML
-  utilities <http://user-mode-linux.sourceforge.net/
-  utilities>  tar file in tools/moo.
-
-
-
-
-
-
-
-
-  8.  Creating filesystems
-
-
-  You may want to create and mount new UML filesystems, either because
-  your root filesystem isn't large enough or because you want to use a
-  filesystem other than ext2.
-
-
-  This was written on the occasion of reiserfs being included in the
-  2.4.1 kernel pool, and therefore the 2.4.1 UML, so the examples will
-  talk about reiserfs.  This information is generic, and the examples
-  should be easy to translate to the filesystem of your choice.
-
-
-  8.1.  Create the filesystem file
-
-  dd is your friend.  All you need to do is tell dd to create an empty
-  file of the appropriate size.  I usually make it sparse to save time
-  and to avoid allocating disk space until it's actually used.  For
-  example, the following command will create a sparse 100 meg file full
-  of zeroes.
-
-
-       host%
-       dd if=/dev/zero of=new_filesystem seek=100 count=1 bs=1M
-
-
-
-
-
-
-  8.2.  Assign the file to a UML device
-
-  Add an argument like the following to the UML command line:
-
-  ubd4=new_filesystem
-
-
-
-
-  making sure that you use an unassigned ubd device number.
-
-
-
-  8.3.  Creating and mounting the filesystem
-
-  Make sure that the filesystem is available, either by being built into
-  the kernel, or available as a module, then boot up UML and log in.  If
-  the root filesystem doesn't have the filesystem utilities (mkfs, fsck,
-  etc), then get them into UML by way of the net or hostfs.
-
-
-  Make the new filesystem on the device assigned to the new file:
-
-
-       host#  mkreiserfs /dev/ubd/4
-
-
-       <----------- MKREISERFSv2 ----------->
-
-       ReiserFS version 3.6.25
-       Block size 4096 bytes
-       Block count 25856
-       Used blocks 8212
-               Journal - 8192 blocks (18-8209), journal header is in block 8210
-               Bitmaps: 17
-               Root block 8211
-       Hash function "r5"
-       ATTENTION: ALL DATA WILL BE LOST ON '/dev/ubd/4'! (y/n)y
-       journal size 8192 (from 18)
-       Initializing journal - 0%....20%....40%....60%....80%....100%
-       Syncing..done.
-
-
-
-
-  Now, mount it:
-
-
-       UML#
-       mount /dev/ubd/4 /mnt
-
-
-
-
-  and you're in business.
-
-
-
-
-
-
-
-
-
-  9.  Host file access
-
-
-  If you want to access files on the host machine from inside UML, you
-  can treat it as a separate machine and either nfs mount directories
-  from the host or copy files into the virtual machine with scp or rcp.
-  However, since UML is running on the host, it can access those
-  files just like any other process and make them available inside the
-  virtual machine without needing to use the network.
-
-
-  This is now possible with the hostfs virtual filesystem.  With it, you
-  can mount a host directory into the UML filesystem and access the
-  files contained in it just as you would on the host.
-
-
-  9.1.  Using hostfs
-
-  To begin with, make sure that hostfs is available inside the virtual
-  machine with
-
-
-       UML# cat /proc/filesystems
-
-
-
-  .  hostfs should be listed.  If it's not, either rebuild the kernel
-  with hostfs configured into it or make sure that hostfs is built as a
-  module and available inside the virtual machine, and insmod it.
-
-
-  Now all you need to do is run mount:
-
-
-       UML# mount none /mnt/host -t hostfs
-
-
-
-
-  will mount the host's / on the virtual machine's /mnt/host.
-
-
-  If you don't want to mount the host root directory, then you can
-  specify a subdirectory to mount with the -o switch to mount:
-
-
-       UML# mount none /mnt/home -t hostfs -o /home
-
-
-
-
-  will mount the hosts's /home on the virtual machine's /mnt/home.
-
-
-
-  9.2.  hostfs as the root filesystem
-
-  It's possible to boot from a directory hierarchy on the host using
-  hostfs rather than using the standard filesystem in a file.
-
-  To start, you need that hierarchy.  The easiest way is to loop mount
-  an existing root_fs file:
-
-
-       host#  mount root_fs uml_root_dir -o loop
-
-
-
-
-  You need to change the filesystem type of / in etc/fstab to be
-  'hostfs', so that line looks like this:
-
-  /dev/ubd/0       /        hostfs      defaults          1   1
-
-
-
-
-  Then you need to chown to yourself all the files in that directory
-  that are owned by root.  This worked for me:
-
-
-       host#  find . -uid 0 -exec chown jdike {} \;
-
-
-
-
-  Next, make sure that your UML kernel has hostfs compiled in, not as a
-  module.  Then run UML with the boot device pointing at that directory:
-
-
-        ubd0=/path/to/uml/root/directory
-
-
-
-
-  UML should then boot as it does normally.
-
-
-  9.3.  Building hostfs
-
-  If you need to build hostfs because it's not in your kernel, you have
-  two choices:
-
-
-
-  o  Compiling hostfs into the kernel:
-
-
-     Reconfigure the kernel and set the 'Host filesystem' option under
-
-
-  o  Compiling hostfs as a module:
-
-
-     Reconfigure the kernel and set the 'Host filesystem' option under
-     be in arch/um/fs/hostfs/hostfs.o.  Install that in
-     /lib/modules/`uname -r`/fs in the virtual machine, boot it up, and
-
-
-       UML# insmod hostfs
-
-
-
-
-
-
-
-
-
-
-
-
-  10.  The Management Console
-
-
-
-  The UML management console is a low-level interface to the kernel,
-  somewhat like the i386 SysRq interface.  Since there is a full-blown
-  operating system under UML, there is much greater flexibility possible
-  than with the SysRq mechanism.
-
-
-  There are a number of things you can do with the mconsole interface:
-
-  o  get the kernel version
-
-  o  add and remove devices
-
-  o  halt or reboot the machine
-
-  o  Send SysRq commands
-
-  o  Pause and resume the UML
-
-
-  You need the mconsole client (uml_mconsole) which is present in CVS
-  (/tools/mconsole) in 2.4.5-9um and later, and will be in the RPM in
-  2.4.6.
-
-
-  You also need CONFIG_MCONSOLE (under 'General Setup') enabled in UML.
-  When you boot UML, you'll see a line like:
-
-
-       mconsole initialized on /home/jdike/.uml/umlNJ32yL/mconsole
-
-
-
-
-  If you specify a unique machine id one the UML command line, i.e.
-
-
-        umid=debian
-
-
-
-
-  you'll see this
-
-
-       mconsole initialized on /home/jdike/.uml/debian/mconsole
-
-
-
-
-  That file is the socket that uml_mconsole will use to communicate with
-  UML.  Run it with either the umid or the full path as its argument:
-
-
-       host% uml_mconsole debian
-
-
-
-
-  or
-
-
-       host% uml_mconsole /home/jdike/.uml/debian/mconsole
-
-
-
-
-  You'll get a prompt, at which you can run one of these commands:
-
-  o  version
-
-  o  halt
-
-  o  reboot
-
-  o  config
-
-  o  remove
-
-  o  sysrq
-
-  o  help
-
-  o  cad
-
-  o  stop
-
-  o  go
-
-
-  10.1.  version
-
-  This takes no arguments.  It prints the UML version.
-
-
-       (mconsole)  version
-       OK Linux usermode 2.4.5-9um #1 Wed Jun 20 22:47:08 EDT 2001 i686
-
-
-
-
-  There are a couple actual uses for this.  It's a simple no-op which
-  can be used to check that a UML is running.  It's also a way of
-  sending an interrupt to the UML.  This is sometimes useful on SMP
-  hosts, where there's a bug which causes signals to UML to be lost,
-  often causing it to appear to hang.  Sending such a UML the mconsole
-  version command is a good way to 'wake it up' before networking has
-  been enabled, as it does not do anything to the function of the UML.
-
-
-
-  10.2.  halt and reboot
-
-  These take no arguments.  They shut the machine down immediately, with
-  no syncing of disks and no clean shutdown of userspace.  So, they are
-  pretty close to crashing the machine.
-
-
-       (mconsole)  halt
-       OK
-
-
-
-
-
-
-  10.3.  config
-
-  "config" adds a new device to the virtual machine.  Currently the ubd
-  and network drivers support this.  It takes one argument, which is the
-  device to add, with the same syntax as the kernel command line.
-
-
-
-
-  (mconsole)
-  config ubd3=/home/jdike/incoming/roots/root_fs_debian22
-
-  OK
-  (mconsole)  config eth1=mcast
-  OK
-
-
-
-
-
-
-  10.4.  remove
-
-  "remove" deletes a device from the system.  Its argument is just the
-  name of the device to be removed. The device must be idle in whatever
-  sense the driver considers necessary.  In the case of the ubd driver,
-  the removed block device must not be mounted, swapped on, or otherwise
-  open, and in the case of the network driver, the device must be down.
-
-
-       (mconsole)  remove ubd3
-       OK
-       (mconsole)  remove eth1
-       OK
-
-
-
-
-
-
-  10.5.  sysrq
-
-  This takes one argument, which is a single letter.  It calls the
-  generic kernel's SysRq driver, which does whatever is called for by
-  that argument.  See the SysRq documentation in
-  Documentation/admin-guide/sysrq.rst in your favorite kernel tree to
-  see what letters are valid and what they do.
-
-
-
-  10.6.  help
-
-  "help" returns a string listing the valid commands and what each one
-  does.
-
-
-
-  10.7.  cad
-
-  This invokes the Ctl-Alt-Del action on init.  What exactly this ends
-  up doing is up to /etc/inittab.  Normally, it reboots the machine.
-  With UML, this is usually not desired, so if a halt would be better,
-  then find the section of inittab that looks like this
-
-
-       # What to do when CTRL-ALT-DEL is pressed.
-       ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
-
-
-
-
-  and change the command to halt.
-
-
-
-  10.8.  stop
-
-  This puts the UML in a loop reading mconsole requests until a 'go'
-  mconsole command is received. This is very useful for making backups
-  of UML filesystems, as the UML can be stopped, then synced via 'sysrq
-  s', so that everything is written to the filesystem. You can then copy
-  the filesystem and then send the UML 'go' via mconsole.
-
-
-  Note that a UML running with more than one CPU will have problems
-  after you send the 'stop' command, as only one CPU will be held in a
-  mconsole loop and all others will continue as normal.  This is a bug,
-  and will be fixed.
-
-
-
-  10.9.  go
-
-  This resumes a UML after being paused by a 'stop' command. Note that
-  when the UML has resumed, TCP connections may have timed out and if
-  the UML is paused for a long period of time, crond might go a little
-  crazy, running all the jobs it didn't do earlier.
-
-
-
-
-
-
-
-
-  11.  Kernel debugging
-
-
-  Note: The interface that makes debugging, as described here, possible
-  is present in 2.4.0-test6 kernels and later.
-
-
-  Since the user-mode kernel runs as a normal Linux process, it is
-  possible to debug it with gdb almost like any other process.  It is
-  slightly different because the kernel's threads are already being
-  ptraced for system call interception, so gdb can't ptrace them.
-  However, a mechanism has been added to work around that problem.
-
-
-  In order to debug the kernel, you need build it from source.  See
-  ``Compiling the kernel and modules''  for information on doing that.
-  Make sure that you enable CONFIG_DEBUGSYM and CONFIG_PT_PROXY during
-  the config.  These will compile the kernel with -g, and enable the
-  ptrace proxy so that gdb works with UML, respectively.
-
-
-
-
-  11.1.  Starting the kernel under gdb
-
-  You can have the kernel running under the control of gdb from the
-  beginning by putting 'debug' on the command line.  You will get an
-  xterm with gdb running inside it.  The kernel will send some commands
-  to gdb which will leave it stopped at the beginning of start_kernel.
-  At this point, you can get things going with 'next', 'step', or
-  'cont'.
-
-
-  There is a transcript of a debugging session  here <debug-
-  session.html> , with breakpoints being set in the scheduler and in an
-  interrupt handler.
-  11.2.  Examining sleeping processes
-
-  Not every bug is evident in the currently running process.  Sometimes,
-  processes hang in the kernel when they shouldn't because they've
-  deadlocked on a semaphore or something similar.  In this case, when
-  you ^C gdb and get a backtrace, you will see the idle thread, which
-  isn't very relevant.
-
-
-  What you want is the stack of whatever process is sleeping when it
-  shouldn't be.  You need to figure out which process that is, which is
-  generally fairly easy.  Then you need to get its host process id,
-  which you can do either by looking at ps on the host or at
-  task.thread.extern_pid in gdb.
-
-
-  Now what you do is this:
-
-  o  detach from the current thread
-
-
-       (UML gdb)  det
-
-
-
-
-
-  o  attach to the thread you are interested in
-
-
-       (UML gdb)  att <host pid>
-
-
-
-
-
-  o  look at its stack and anything else of interest
-
-
-       (UML gdb)  bt
-
-
-
-
-  Note that you can't do anything at this point that requires that a
-  process execute, e.g. calling a function
-
-  o  when you're done looking at that process, reattach to the current
-     thread and continue it
-
-
-       (UML gdb)
-       att 1
-
-
-
-
-
-
-       (UML gdb)
-       c
-
-
-
-
-  Here, specifying any pid which is not the process id of a UML thread
-  will cause gdb to reattach to the current thread.  I commonly use 1,
-  but any other invalid pid would work.
-
-
-
-  11.3.  Running ddd on UML
-
-  ddd works on UML, but requires a special kludge.  The process goes
-  like this:
-
-  o  Start ddd
-
-
-       host% ddd linux
-
-
-
-
-
-  o  With ps, get the pid of the gdb that ddd started.  You can ask the
-     gdb to tell you, but for some reason that confuses things and
-     causes a hang.
-
-  o  run UML with 'debug=parent gdb-pid=<pid>' added to the command line
-     - it will just sit there after you hit return
-
-  o  type 'att 1' to the ddd gdb and you will see something like
-
-
-       0xa013dc51 in __kill ()
-
-
-       (gdb)
-
-
-
-
-
-  o  At this point, type 'c', UML will boot up, and you can use ddd just
-     as you do on any other process.
-
-
-
-  11.4.  Debugging modules
-
-  gdb has support for debugging code which is dynamically loaded into
-  the process.  This support is what is needed to debug kernel modules
-  under UML.
-
-
-  Using that support is somewhat complicated.  You have to tell gdb what
-  object file you just loaded into UML and where in memory it is.  Then,
-  it can read the symbol table, and figure out where all the symbols are
-  from the load address that you provided.  It gets more interesting
-  when you load the module again (i.e. after an rmmod).  You have to
-  tell gdb to forget about all its symbols, including the main UML ones
-  for some reason, then load then all back in again.
-
-
-  There's an easy way and a hard way to do this.  The easy way is to use
-  the umlgdb expect script written by Chandan Kudige.  It basically
-  automates the process for you.
-
-
-  First, you must tell it where your modules are.  There is a list in
-  the script that looks like this:
-       set MODULE_PATHS {
-       "fat" "/usr/src/uml/linux-2.4.18/fs/fat/fat.o"
-       "isofs" "/usr/src/uml/linux-2.4.18/fs/isofs/isofs.o"
-       "minix" "/usr/src/uml/linux-2.4.18/fs/minix/minix.o"
-       }
-
-
-
-
-  You change that to list the names and paths of the modules that you
-  are going to debug.  Then you run it from the toplevel directory of
-  your UML pool and it basically tells you what to do:
-
-
-
-
-                   ******** GDB pid is 21903 ********
-       Start UML as: ./linux <kernel switches> debug gdb-pid=21903
-
-
-
-       GNU gdb 5.0rh-5 Red Hat Linux 7.1
-       Copyright 2001 Free Software Foundation, Inc.
-       GDB is free software, covered by the GNU General Public License, and you are
-       welcome to change it and/or distribute copies of it under certain conditions.
-       Type "show copying" to see the conditions.
-       There is absolutely no warranty for GDB.  Type "show warranty" for details.
-       This GDB was configured as "i386-redhat-linux"...
-       (gdb) b sys_init_module
-       Breakpoint 1 at 0xa0011923: file module.c, line 349.
-       (gdb) att 1
-
-
-
-
-  After you run UML and it sits there doing nothing, you hit return at
-  the 'att 1' and continue it:
-
-
-       Attaching to program: /home/jdike/linux/2.4/um/./linux, process 1
-       0xa00f4221 in __kill ()
-       (UML gdb)  c
-       Continuing.
-
-
-
-
-  At this point, you debug normally.  When you insmod something, the
-  expect magic will kick in and you'll see something like:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-   *** Module hostfs loaded ***
-  Breakpoint 1, sys_init_module (name_user=0x805abb0 "hostfs",
-      mod_user=0x8070e00) at module.c:349
-  349             char *name, *n_name, *name_tmp = NULL;
-  (UML gdb)  finish
-  Run till exit from #0  sys_init_module (name_user=0x805abb0 "hostfs",
-      mod_user=0x8070e00) at module.c:349
-  0xa00e2e23 in execute_syscall (r=0xa8140284) at syscall_kern.c:411
-  411             else res = EXECUTE_SYSCALL(syscall, regs);
-  Value returned is $1 = 0
-  (UML gdb)
-  p/x (int)module_list + module_list->size_of_struct
-
-  $2 = 0xa9021054
-  (UML gdb)  symbol-file ./linux
-  Load new symbol table from "./linux"? (y or n) y
-  Reading symbols from ./linux...
-  done.
-  (UML gdb)
-  add-symbol-file /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o 0xa9021054
-
-  add symbol table from file "/home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o" at
-          .text_addr = 0xa9021054
-   (y or n) y
-
-  Reading symbols from /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o...
-  done.
-  (UML gdb)  p *module_list
-  $1 = {size_of_struct = 84, next = 0xa0178720, name = 0xa9022de0 "hostfs",
-    size = 9016, uc = {usecount = {counter = 0}, pad = 0}, flags = 1,
-    nsyms = 57, ndeps = 0, syms = 0xa9023170, deps = 0x0, refs = 0x0,
-    init = 0xa90221f0 <init_hostfs>, cleanup = 0xa902222c <exit_hostfs>,
-    ex_table_start = 0x0, ex_table_end = 0x0, persist_start = 0x0,
-    persist_end = 0x0, can_unload = 0, runsize = 0, kallsyms_start = 0x0,
-    kallsyms_end = 0x0,
-    archdata_start = 0x1b855 <Address 0x1b855 out of bounds>,
-    archdata_end = 0xe5890000 <Address 0xe5890000 out of bounds>,
-    kernel_data = 0xf689c35d <Address 0xf689c35d out of bounds>}
-  >> Finished loading symbols for hostfs ...
-
-
-
-
-  That's the easy way.  It's highly recommended.  The hard way is
-  described below in case you're interested in what's going on.
-
-
-  Boot the kernel under the debugger and load the module with insmod or
-  modprobe.  With gdb, do:
-
-
-       (UML gdb)  p module_list
-
-
-
-
-  This is a list of modules that have been loaded into the kernel, with
-  the most recently loaded module first.  Normally, the module you want
-  is at module_list.  If it's not, walk down the next links, looking at
-  the name fields until find the module you want to debug.  Take the
-  address of that structure, and add module.size_of_struct (which in
-  2.4.10 kernels is 96 (0x60)) to it.  Gdb can make this hard addition
-  for you :-):
-
-
-
-  (UML gdb)
-  printf "%#x\n", (int)module_list module_list->size_of_struct
-
-
-
-
-  The offset from the module start occasionally changes (before 2.4.0,
-  it was module.size_of_struct + 4), so it's a good idea to check the
-  init and cleanup addresses once in a while, as describe below.  Now
-  do:
-
-
-       (UML gdb)
-       add-symbol-file /path/to/module/on/host that_address
-
-
-
-
-  Tell gdb you really want to do it, and you're in business.
-
-
-  If there's any doubt that you got the offset right, like breakpoints
-  appear not to work, or they're appearing in the wrong place, you can
-  check it by looking at the module structure.  The init and cleanup
-  fields should look like:
-
-
-       init = 0x588066b0 <init_hostfs>, cleanup = 0x588066c0 <exit_hostfs>
-
-
-
-
-  with no offsets on the symbol names.  If the names are right, but they
-  are offset, then the offset tells you how much you need to add to the
-  address you gave to add-symbol-file.
-
-
-  When you want to load in a new version of the module, you need to get
-  gdb to forget about the old one.  The only way I've found to do that
-  is to tell gdb to forget about all symbols that it knows about:
-
-
-       (UML gdb)  symbol-file
-
-
-
-
-  Then reload the symbols from the kernel binary:
-
-
-       (UML gdb)  symbol-file /path/to/kernel
-
-
-
-
-  and repeat the process above.  You'll also need to re-enable break-
-  points.  They were disabled when you dumped all the symbols because
-  gdb couldn't figure out where they should go.
-
-
-
-  11.5.  Attaching gdb to the kernel
-
-  If you don't have the kernel running under gdb, you can attach gdb to
-  it later by sending the tracing thread a SIGUSR1.  The first line of
-  the console output identifies its pid:
-       tracing thread pid = 20093
-
-
-
-
-  When you send it the signal:
-
-
-       host% kill -USR1 20093
-
-
-
-
-  you will get an xterm with gdb running in it.
-
-
-  If you have the mconsole compiled into UML, then the mconsole client
-  can be used to start gdb:
-
-
-       (mconsole)  (mconsole) config gdb=xterm
-
-
-
-
-  will fire up an xterm with gdb running in it.
-
-
-
-  11.6.  Using alternate debuggers
-
-  UML has support for attaching to an already running debugger rather
-  than starting gdb itself.  This is present in CVS as of 17 Apr 2001.
-  I sent it to Alan for inclusion in the ac tree, and it will be in my
-  2.4.4 release.
-
-
-  This is useful when gdb is a subprocess of some UI, such as emacs or
-  ddd.  It can also be used to run debuggers other than gdb on UML.
-  Below is an example of using strace as an alternate debugger.
-
-
-  To do this, you need to get the pid of the debugger and pass it in
-  with the
-
-
-  If you are using gdb under some UI, then tell it to 'att 1', and
-  you'll find yourself attached to UML.
-
-
-  If you are using something other than gdb as your debugger, then
-  you'll need to get it to do the equivalent of 'att 1' if it doesn't do
-  it automatically.
-
-
-  An example of an alternate debugger is strace.  You can strace the
-  actual kernel as follows:
-
-  o  Run the following in a shell
-
-
-       host%
-       sh -c 'echo pid=$$; echo -n hit return; read x; exec strace -p 1 -o strace.out'
-
-
-
-  o  Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
-     by the previous command
-
-  o  Hit return in the shell, and UML will start running, and strace
-     output will start accumulating in the output file.
-
-     Note that this is different from running
-
-
-       host% strace ./linux
-
-
-
-
-  That will strace only the main UML thread, the tracing thread, which
-  doesn't do any of the actual kernel work.  It just oversees the vir-
-  tual machine.  In contrast, using strace as described above will show
-  you the low-level activity of the virtual machine.
-
-
-
-
-
-  12.  Kernel debugging examples
-
-  12.1.  The case of the hung fsck
-
-  When booting up the kernel, fsck failed, and dropped me into a shell
-  to fix things up.  I ran fsck -y, which hung:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  Setting hostname uml                    [ OK ]
-  Checking root filesystem
-  /dev/fhd0 was not cleanly unmounted, check forced.
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
-
-  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
-          (i.e., without -a or -p options)
-  [ FAILED ]
-
-  *** An error occurred during the file system check.
-  *** Dropping you to a shell; the system will reboot
-  *** when you leave the shell.
-  Give root password for maintenance
-  (or type Control-D for normal startup):
-
-  [root@uml /root]# fsck -y /dev/fhd0
-  fsck -y /dev/fhd0
-  Parallelizing fsck version 1.14 (9-Jan-1999)
-  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
-  /dev/fhd0 contains a file system with errors, check forced.
-  Pass 1: Checking inodes, blocks, and sizes
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
-
-  Inode 19780, i_blocks is 1548, should be 540.  Fix? yes
-
-  Pass 2: Checking directory structure
-  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
-
-  Directory inode 11858, block 0, offset 0: directory corrupted
-  Salvage? yes
-
-  Missing '.' in directory inode 11858.
-  Fix? yes
-
-  Missing '..' in directory inode 11858.
-  Fix? yes
-
-
-
-
-
-  The standard drill in this sort of situation is to fire up gdb on the
-  signal thread, which, in this case, was pid 1935.  In another window,
-  I run gdb and attach pid 1935.
-
-
-
-
-       ~/linux/2.3.26/um 1016: gdb linux
-       GNU gdb 4.17.0.11 with Linux support
-       Copyright 1998 Free Software Foundation, Inc.
-       GDB is free software, covered by the GNU General Public License, and you are
-       welcome to change it and/or distribute copies of it under certain conditions.
-       Type "show copying" to see the conditions.
-       There is absolutely no warranty for GDB.  Type "show warranty" for details.
-       This GDB was configured as "i386-redhat-linux"...
-
-       (gdb) att 1935
-       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1935
-       0x100756d9 in __wait4 ()
-
-
-
-
-
-
-  Let's see what's currently running:
-
-
-
-       (gdb) p current_task.pid
-       $1 = 0
-
-
-
-
-
-  It's the idle thread, which means that fsck went to sleep for some
-  reason and never woke up.
-
-
-  Let's guess that the last process in the process list is fsck:
-
-
-
-       (gdb) p current_task.prev_task.comm
-       $13 = "fsck.ext2\000\000\000\000\000\000"
-
-
-
-
-
-  It is, so let's see what it thinks it's up to:
-
-
-
-       (gdb) p current_task.prev_task.thread
-       $14 = {extern_pid = 1980, tracing = 0, want_tracing = 0, forking = 0,
-         kernel_stack_page = 0, signal_stack = 1342627840, syscall = {id = 4, args = {
-             3, 134973440, 1024, 0, 1024}, have_result = 0, result = 50590720},
-         request = {op = 2, u = {exec = {ip = 1350467584, sp = 2952789424}, fork = {
-               regs = {1350467584, 2952789424, 0 <repeats 15 times>}, sigstack = 0,
-               pid = 0}, switch_to = 0x507e8000, thread = {proc = 0x507e8000,
-               arg = 0xaffffdb0, flags = 0, new_pid = 0}, input_request = {
-               op = 1350467584, fd = -1342177872, proc = 0, pid = 0}}}}
-
-
-
-
-
-  The interesting things here are the fact that its .thread.syscall.id
-  is __NR_write (see the big switch in arch/um/kernel/syscall_kern.c or
-  the defines in include/asm-um/arch/unistd.h), and that it never
-  returned.  Also, its .request.op is OP_SWITCH (see
-  arch/um/include/user_util.h).  These mean that it went into a write,
-  and, for some reason, called schedule().
-
-
-  The fact that it never returned from write means that its stack should
-  be fairly interesting.  Its pid is 1980 (.thread.extern_pid).  That
-  process is being ptraced by the signal thread, so it must be detached
-  before gdb can attach it:
-
-
-
-
-
-
-
-
-
-
-  (gdb) call detach(1980)
-
-  Program received signal SIGSEGV, Segmentation fault.
-  <function called from gdb>
-  The program being debugged stopped while in a function called from GDB.
-  When the function (detach) is done executing, GDB will silently
-  stop (instead of continuing to evaluate the expression containing
-  the function call).
-  (gdb) call detach(1980)
-  $15 = 0
-
-
-
-
-
-  The first detach segfaults for some reason, and the second one
-  succeeds.
-
-
-  Now I detach from the signal thread, attach to the fsck thread, and
-  look at its stack:
-
-
-       (gdb) det
-       Detaching from program: /home/dike/linux/2.3.26/um/linux Pid 1935
-       (gdb) att 1980
-       Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1980
-       0x10070451 in __kill ()
-       (gdb) bt
-       #0  0x10070451 in __kill ()
-       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
-       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
-           at process_kern.c:156
-       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
-           at process_kern.c:161
-       #4  0x10001d12 in schedule () at core.c:777
-       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
-       #6  0x1006aa10 in __down_failed () at semaphore.c:157
-       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
-       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
-       #9  <signal handler called>
-       #10 0x10155404 in errno ()
-       #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
-       #12 0x1006c5d8 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
-       #13 0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
-       #14 <signal handler called>
-       #15 0xc0fd in ?? ()
-       #16 0x10016647 in sys_write (fd=3,
-           buf=0x80b8800 <Address 0x80b8800 out of bounds>, count=1024)
-           at read_write.c:159
-       #17 0x1006d5b3 in execute_syscall (syscall=4, args=0x5006ef08)
-           at syscall_kern.c:254
-       #18 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
-       #19 <signal handler called>
-       #20 0x400dc8b0 in ?? ()
-
-
-
-
-
-  The interesting things here are :
-
-  o  There are two segfaults on this stack (frames 9 and 14)
-
-  o  The first faulting address (frame 11) is 0x50000800
-
-  (gdb) p (void *)1342179328
-  $16 = (void *) 0x50000800
-
-
-
-
-
-  The initial faulting address is interesting because it is on the idle
-  thread's stack.  I had been seeing the idle thread segfault for no
-  apparent reason, and the cause looked like stack corruption.  In hopes
-  of catching the culprit in the act, I had turned off all protections
-  to that stack while the idle thread wasn't running.  This apparently
-  tripped that trap.
-
-
-  However, the more immediate problem is that second segfault and I'm
-  going to concentrate on that.  First, I want to see where the fault
-  happened, so I have to go look at the sigcontent struct in frame 8:
-
-
-
-       (gdb) up
-       #1  0x10068ccd in usr1_pid (pid=1980) at process.c:30
-       30        kill(pid, SIGUSR1);
-       (gdb)
-       #2  0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
-           at process_kern.c:156
-       156       usr1_pid(getpid());
-       (gdb)
-       #3  0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
-           at process_kern.c:161
-       161       _switch_to(prev, next);
-       (gdb)
-       #4  0x10001d12 in schedule () at core.c:777
-       777             switch_to(prev, next, prev);
-       (gdb)
-       #5  0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
-       71                      schedule();
-       (gdb)
-       #6  0x1006aa10 in __down_failed () at semaphore.c:157
-       157     }
-       (gdb)
-       #7  0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
-       174       segv(sc->cr2, sc->err & 2);
-       (gdb)
-       #8  0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
-       182       segv_handler(sc);
-       (gdb) p *sc
-       Cannot access memory at address 0x0.
-
-
-
-
-  That's not very useful, so I'll try a more manual method:
-
-
-       (gdb) p *((struct sigcontext *) (&sig + 1))
-       $19 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
-         __dsh = 0, edi = 1342179328, esi = 1350378548, ebp = 1342630440,
-         esp = 1342630420, ebx = 1348150624, edx = 1280, ecx = 0, eax = 0,
-         trapno = 14, err = 4, eip = 268480945, cs = 35, __csh = 0, eflags = 66118,
-         esp_at_signal = 1342630420, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
-         cr2 = 1280}
-
-
-
-  The ip is in handle_mm_fault:
-
-
-       (gdb) p (void *)268480945
-       $20 = (void *) 0x1000b1b1
-       (gdb) i sym $20
-       handle_mm_fault + 57 in section .text
-
-
-
-
-
-  Specifically, it's in pte_alloc:
-
-
-       (gdb) i line *$20
-       Line 124 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1b1 <handle_mm_fault+57>
-          and ends at 0x1000b1b7 <handle_mm_fault+63>.
-
-
-
-
-
-  To find where in handle_mm_fault this is, I'll jump forward in the
-  code until I see an address in that procedure:
-
-
-
-       (gdb) i line *0x1000b1c0
-       Line 126 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1b7 <handle_mm_fault+63>
-          and ends at 0x1000b1c3 <handle_mm_fault+75>.
-       (gdb) i line *0x1000b1d0
-       Line 131 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1d0 <handle_mm_fault+88>
-          and ends at 0x1000b1da <handle_mm_fault+98>.
-       (gdb) i line *0x1000b1e0
-       Line 61 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1da <handle_mm_fault+98>
-          and ends at 0x1000b1e1 <handle_mm_fault+105>.
-       (gdb) i line *0x1000b1f0
-       Line 134 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b1f0 <handle_mm_fault+120>
-          and ends at 0x1000b200 <handle_mm_fault+136>.
-       (gdb) i line *0x1000b200
-       Line 135 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b200 <handle_mm_fault+136>
-          and ends at 0x1000b208 <handle_mm_fault+144>.
-       (gdb) i line *0x1000b210
-       Line 139 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
-          starts at address 0x1000b210 <handle_mm_fault+152>
-          and ends at 0x1000b219 <handle_mm_fault+161>.
-       (gdb) i line *0x1000b220
-       Line 1168 of "memory.c" starts at address 0x1000b21e <handle_mm_fault+166>
-          and ends at 0x1000b222 <handle_mm_fault+170>.
-
-
-
-
-
-  Something is apparently wrong with the page tables or vma_structs, so
-  lets go back to frame 11 and have a look at them:
-
-
-
-  #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
-  50        handle_mm_fault(current, vma, address, is_write);
-  (gdb) call pgd_offset_proc(vma->vm_mm, address)
-  $22 = (pgd_t *) 0x80a548c
-
-
-
-
-
-  That's pretty bogus.  Page tables aren't supposed to be in process
-  text or data areas.  Let's see what's in the vma:
-
-
-       (gdb) p *vma
-       $23 = {vm_mm = 0x507d2434, vm_start = 0, vm_end = 134512640,
-         vm_next = 0x80a4f8c, vm_page_prot = {pgprot = 0}, vm_flags = 31200,
-         vm_avl_height = 2058, vm_avl_left = 0x80a8c94, vm_avl_right = 0x80d1000,
-         vm_next_share = 0xaffffdb0, vm_pprev_share = 0xaffffe63,
-         vm_ops = 0xaffffe7a, vm_pgoff = 2952789626, vm_file = 0xafffffec,
-         vm_private_data = 0x62}
-       (gdb) p *vma.vm_mm
-       $24 = {mmap = 0x507d2434, mmap_avl = 0x0, mmap_cache = 0x8048000,
-         pgd = 0x80a4f8c, mm_users = {counter = 0}, mm_count = {counter = 134904288},
-         map_count = 134909076, mmap_sem = {count = {counter = 135073792},
-           sleepers = -1342177872, wait = {lock = <optimized out or zero length>,
-             task_list = {next = 0xaffffe63, prev = 0xaffffe7a},
-             __magic = -1342177670, __creator = -1342177300}, __magic = 98},
-         page_table_lock = {}, context = 138, start_code = 0, end_code = 0,
-         start_data = 0, end_data = 0, start_brk = 0, brk = 0, start_stack = 0,
-         arg_start = 0, arg_end = 0, env_start = 0, env_end = 0, rss = 1350381536,
-         total_vm = 0, locked_vm = 0, def_flags = 0, cpu_vm_mask = 0, swap_cnt = 0,
-         swap_address = 0, segments = 0x0}
-
-
-
-
-
-  This also pretty bogus.  With all of the 0x80xxxxx and 0xaffffxxx
-  addresses, this is looking like a stack was plonked down on top of
-  these structures.  Maybe it's a stack overflow from the next page:
-
-
-
-       (gdb) p vma
-       $25 = (struct vm_area_struct *) 0x507d2434
-
-
-
-
-
-  That's towards the lower quarter of the page, so that would have to
-  have been pretty heavy stack overflow:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  (gdb) x/100x $25
-  0x507d2434:     0x507d2434      0x00000000      0x08048000      0x080a4f8c
-  0x507d2444:     0x00000000      0x080a79e0      0x080a8c94      0x080d1000
-  0x507d2454:     0xaffffdb0      0xaffffe63      0xaffffe7a      0xaffffe7a
-  0x507d2464:     0xafffffec      0x00000062      0x0000008a      0x00000000
-  0x507d2474:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2484:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2494:     0x00000000      0x00000000      0x507d2fe0      0x00000000
-  0x507d24a4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24b4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24c4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24d4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24e4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d24f4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2504:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2514:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2524:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2534:     0x00000000      0x00000000      0x507d25dc      0x00000000
-  0x507d2544:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2554:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2564:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2574:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2584:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d2594:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d25a4:     0x00000000      0x00000000      0x00000000      0x00000000
-  0x507d25b4:     0x00000000      0x00000000      0x00000000      0x00000000
-
-
-
-
-
-  It's not stack overflow.  The only "stack-like" piece of this data is
-  the vma_struct itself.
-
-
-  At this point, I don't see any avenues to pursue, so I just have to
-  admit that I have no idea what's going on.  What I will do, though, is
-  stick a trap on the segfault handler which will stop if it sees any
-  writes to the idle thread's stack.  That was the thing that happened
-  first, and it may be that if I can catch it immediately, what's going
-  on will be somewhat clearer.
-
-
-  12.2.  Episode 2: The case of the hung fsck
-
-  After setting a trap in the SEGV handler for accesses to the signal
-  thread's stack, I reran the kernel.
-
-
-  fsck hung again, this time by hitting the trap:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  Setting hostname uml                            [ OK ]
-  Checking root filesystem
-  /dev/fhd0 contains a file system with errors, check forced.
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
-
-  /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
-          (i.e., without -a or -p options)
-  [ FAILED ]
-
-  *** An error occurred during the file system check.
-  *** Dropping you to a shell; the system will reboot
-  *** when you leave the shell.
-  Give root password for maintenance
-  (or type Control-D for normal startup):
-
-  [root@uml /root]# fsck -y /dev/fhd0
-  fsck -y /dev/fhd0
-  Parallelizing fsck version 1.14 (9-Jan-1999)
-  e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
-  /dev/fhd0 contains a file system with errors, check forced.
-  Pass 1: Checking inodes, blocks, and sizes
-  Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.  Ignore error? yes
-
-  Pass 2: Checking directory structure
-  Error reading block 49405 (Attempt to read block from filesystem resulted in short read).  Ignore error? yes
-
-  Directory inode 11858, block 0, offset 0: directory corrupted
-  Salvage? yes
-
-  Missing '.' in directory inode 11858.
-  Fix? yes
-
-  Missing '..' in directory inode 11858.
-  Fix? yes
-
-  Untested (4127) [100fe44c]: trap_kern.c line 31
-
-
-
-
-
-  I need to get the signal thread to detach from pid 4127 so that I can
-  attach to it with gdb.  This is done by sending it a SIGUSR1, which is
-  caught by the signal thread, which detaches the process:
-
-
-       kill -USR1 4127
-
-
-
-
-
-  Now I can run gdb on it:
-
-
-
-
-
-
-
-
-
-
-
-
-
-  ~/linux/2.3.26/um 1034: gdb linux
-  GNU gdb 4.17.0.11 with Linux support
-  Copyright 1998 Free Software Foundation, Inc.
-  GDB is free software, covered by the GNU General Public License, and you are
-  welcome to change it and/or distribute copies of it under certain conditions.
-  Type "show copying" to see the conditions.
-  There is absolutely no warranty for GDB.  Type "show warranty" for details.
-  This GDB was configured as "i386-redhat-linux"...
-  (gdb) att 4127
-  Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 4127
-  0x10075891 in __libc_nanosleep ()
-
-
-
-
-
-  The backtrace shows that it was in a write and that the fault address
-  (address in frame 3) is 0x50000800, which is right in the middle of
-  the signal thread's stack page:
-
-
-       (gdb) bt
-       #0  0x10075891 in __libc_nanosleep ()
-       #1  0x1007584d in __sleep (seconds=1000000)
-           at ../sysdeps/unix/sysv/linux/sleep.c:78
-       #2  0x1006ce9a in stop () at user_util.c:191
-       #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
-       #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
-       #5  0x1006c63c in kern_segv_handler (sig=11) at trap_user.c:182
-       #6  <signal handler called>
-       #7  0xc0fd in ?? ()
-       #8  0x10016647 in sys_write (fd=3, buf=0x80b8800 "R.", count=1024)
-           at read_write.c:159
-       #9  0x1006d603 in execute_syscall (syscall=4, args=0x5006ef08)
-           at syscall_kern.c:254
-       #10 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
-       #11 <signal handler called>
-       #12 0x400dc8b0 in ?? ()
-       #13 <signal handler called>
-       #14 0x400dc8b0 in ?? ()
-       #15 0x80545fd in ?? ()
-       #16 0x804daae in ?? ()
-       #17 0x8054334 in ?? ()
-       #18 0x804d23e in ?? ()
-       #19 0x8049632 in ?? ()
-       #20 0x80491d2 in ?? ()
-       #21 0x80596b5 in ?? ()
-       (gdb) p (void *)1342179328
-       $3 = (void *) 0x50000800
-
-
-
-
-
-  Going up the stack to the segv_handler frame and looking at where in
-  the code the access happened shows that it happened near line 110 of
-  block_dev.c:
-
-
-
-
-
-
-
-
-
-  (gdb) up
-  #1  0x1007584d in __sleep (seconds=1000000)
-      at ../sysdeps/unix/sysv/linux/sleep.c:78
-  ../sysdeps/unix/sysv/linux/sleep.c:78: No such file or directory.
-  (gdb)
-  #2  0x1006ce9a in stop () at user_util.c:191
-  191       while(1) sleep(1000000);
-  (gdb)
-  #3  0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
-  31          KERN_UNTESTED();
-  (gdb)
-  #4  0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
-  174       segv(sc->cr2, sc->err & 2);
-  (gdb) p *sc
-  $1 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
-    __dsh = 0, edi = 1342179328, esi = 134973440, ebp = 1342631484,
-    esp = 1342630864, ebx = 256, edx = 0, ecx = 256, eax = 1024, trapno = 14,
-    err = 6, eip = 268550834, cs = 35, __csh = 0, eflags = 66070,
-    esp_at_signal = 1342630864, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
-    cr2 = 1342179328}
-  (gdb) p (void *)268550834
-  $2 = (void *) 0x1001c2b2
-  (gdb) i sym $2
-  block_write + 1090 in section .text
-  (gdb) i line *$2
-  Line 209 of "/home/dike/linux/2.3.26/um/include/asm/arch/string.h"
-     starts at address 0x1001c2a1 <block_write+1073>
-     and ends at 0x1001c2bf <block_write+1103>.
-  (gdb) i line *0x1001c2c0
-  Line 110 of "block_dev.c" starts at address 0x1001c2bf <block_write+1103>
-     and ends at 0x1001c2e3 <block_write+1139>.
-
-
-
-
-
-  Looking at the source shows that the fault happened during a call to
-  copy_from_user to copy the data into the kernel:
-
-
-       107             count -= chars;
-       108             copy_from_user(p,buf,chars);
-       109             p += chars;
-       110             buf += chars;
-
-
-
-
-
-  p is the pointer which must contain 0x50000800, since buf contains
-  0x80b8800 (frame 8 above).  It is defined as:
-
-
-                       p = offset + bh->b_data;
-
-
-
-
-
-  I need to figure out what bh is, and it just so happens that bh is
-  passed as an argument to mark_buffer_uptodate and mark_buffer_dirty a
-  few lines later, so I do a little disassembly:
-
-
-
-
-  (gdb) disas 0x1001c2bf 0x1001c2e0
-  Dump of assembler code from 0x1001c2bf to 0x1001c2d0:
-  0x1001c2bf <block_write+1103>:  addl   %eax,0xc(%ebp)
-  0x1001c2c2 <block_write+1106>:  movl   0xfffffdd4(%ebp),%edx
-  0x1001c2c8 <block_write+1112>:  btsl   $0x0,0x18(%edx)
-  0x1001c2cd <block_write+1117>:  btsl   $0x1,0x18(%edx)
-  0x1001c2d2 <block_write+1122>:  sbbl   %ecx,%ecx
-  0x1001c2d4 <block_write+1124>:  testl  %ecx,%ecx
-  0x1001c2d6 <block_write+1126>:  jne    0x1001c2e3 <block_write+1139>
-  0x1001c2d8 <block_write+1128>:  pushl  $0x0
-  0x1001c2da <block_write+1130>:  pushl  %edx
-  0x1001c2db <block_write+1131>:  call   0x1001819c <__mark_buffer_dirty>
-  End of assembler dump.
-
-
-
-
-
-  At that point, bh is in %edx (address 0x1001c2da), which is calculated
-  at 0x1001c2c2 as %ebp + 0xfffffdd4, so I figure exactly what that is,
-  taking %ebp from the sigcontext_struct above:
-
-
-       (gdb) p (void *)1342631484
-       $5 = (void *) 0x5006ee3c
-       (gdb) p 0x5006ee3c+0xfffffdd4
-       $6 = 1342630928
-       (gdb) p (void *)$6
-       $7 = (void *) 0x5006ec10
-       (gdb) p *((void **)$7)
-       $8 = (void *) 0x50100200
-
-
-
-
-
-  Now, I look at the structure to see what's in it, and particularly,
-  what its b_data field contains:
-
-
-       (gdb) p *((struct buffer_head *)0x50100200)
-       $13 = {b_next = 0x50289380, b_blocknr = 49405, b_size = 1024, b_list = 0,
-         b_dev = 15872, b_count = {counter = 1}, b_rdev = 15872, b_state = 24,
-         b_flushtime = 0, b_next_free = 0x501001a0, b_prev_free = 0x50100260,
-         b_this_page = 0x501001a0, b_reqnext = 0x0, b_pprev = 0x507fcf58,
-         b_data = 0x50000800 "", b_page = 0x50004000,
-         b_end_io = 0x10017f60 <end_buffer_io_sync>, b_dev_id = 0x0,
-         b_rsector = 98810, b_wait = {lock = <optimized out or zero length>,
-           task_list = {next = 0x50100248, prev = 0x50100248}, __magic = 1343226448,
-           __creator = 0}, b_kiobuf = 0x0}
-
-
-
-
-
-  The b_data field is indeed 0x50000800, so the question becomes how
-  that happened.  The rest of the structure looks fine, so this probably
-  is not a case of data corruption.  It happened on purpose somehow.
-
-
-  The b_page field is a pointer to the page_struct representing the
-  0x50000000 page.  Looking at it shows the kernel's idea of the state
-  of that page:
-
-
-
-  (gdb) p *$13.b_page
-  $17 = {list = {next = 0x50004a5c, prev = 0x100c5174}, mapping = 0x0,
-    index = 0, next_hash = 0x0, count = {counter = 1}, flags = 132, lru = {
-      next = 0x50008460, prev = 0x50019350}, wait = {
-      lock = <optimized out or zero length>, task_list = {next = 0x50004024,
-        prev = 0x50004024}, __magic = 1342193708, __creator = 0},
-    pprev_hash = 0x0, buffers = 0x501002c0, virtual = 1342177280,
-    zone = 0x100c5160}
-
-
-
-
-
-  Some sanity-checking: the virtual field shows the "virtual" address of
-  this page, which in this kernel is the same as its "physical" address,
-  and the page_struct itself should be mem_map[0], since it represents
-  the first page of memory:
-
-
-
-       (gdb) p (void *)1342177280
-       $18 = (void *) 0x50000000
-       (gdb) p mem_map
-       $19 = (mem_map_t *) 0x50004000
-
-
-
-
-
-  These check out fine.
-
-
-  Now to check out the page_struct itself.  In particular, the flags
-  field shows whether the page is considered free or not:
-
-
-       (gdb) p (void *)132
-       $21 = (void *) 0x84
-
-
-
-
-
-  The "reserved" bit is the high bit, which is definitely not set, so
-  the kernel considers the signal stack page to be free and available to
-  be used.
-
-
-  At this point, I jump to conclusions and start looking at my early
-  boot code, because that's where that page is supposed to be reserved.
-
-
-  In my setup_arch procedure, I have the following code which looks just
-  fine:
-
-
-
-       bootmap_size = init_bootmem(start_pfn, end_pfn - start_pfn);
-       free_bootmem(__pa(low_physmem) + bootmap_size, high_physmem - low_physmem);
-
-
-
-
-
-  Two stack pages have already been allocated, and low_physmem points to
-  the third page, which is the beginning of free memory.
-  The init_bootmem call declares the entire memory to the boot memory
-  manager, which marks it all reserved.  The free_bootmem call frees up
-  all of it, except for the first two pages.  This looks correct to me.
-
-
-  So, I decide to see init_bootmem run and make sure that it is marking
-  those first two pages as reserved.  I never get that far.
-
-
-  Stepping into init_bootmem, and looking at bootmem_map before looking
-  at what it contains shows the following:
-
-
-
-       (gdb) p bootmem_map
-       $3 = (void *) 0x50000000
-
-
-
-
-
-  Aha!  The light dawns.  That first page is doing double duty as a
-  stack and as the boot memory map.  The last thing that the boot memory
-  manager does is to free the pages used by its memory map, so this page
-  is getting freed even its marked as reserved.
-
-
-  The fix was to initialize the boot memory manager before allocating
-  those two stack pages, and then allocate them through the boot memory
-  manager.  After doing this, and fixing a couple of subsequent buglets,
-  the stack corruption problem disappeared.
-
-
-
-
-
-  13.  What to do when UML doesn't work
-
-
-
-
-  13.1.  Strange compilation errors when you build from source
-
-  As of test11, it is necessary to have "ARCH=um" in the environment or
-  on the make command line for all steps in building UML, including
-  clean, distclean, or mrproper, config, menuconfig, or xconfig, dep,
-  and linux.  If you forget for any of them, the i386 build seems to
-  contaminate the UML build.  If this happens, start from scratch with
-
-
-       host%
-       make mrproper ARCH=um
-
-
-
-
-  and repeat the build process with ARCH=um on all the steps.
-
-
-  See ``Compiling the kernel and modules''  for more details.
-
-
-  Another cause of strange compilation errors is building UML in
-  /usr/src/linux.  If you do this, the first thing you need to do is
-  clean up the mess you made.  The /usr/src/linux/asm link will now
-  point to /usr/src/linux/asm-um.  Make it point back to
-  /usr/src/linux/asm-i386.  Then, move your UML pool someplace else and
-  build it there.  Also see below, where a more specific set of symptoms
-  is described.
-
-
-
-  13.3.  A variety of panics and hangs with /tmp on a reiserfs  filesys-
-  tem
-
-  I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
-  Panics preceded by
-
-
-       Detaching pid nnnn
-
-
-
-  are diagnostic of this problem.  This is a reiserfs bug which causes a
-  thread to occasionally read stale data from a mmapped page shared with
-  another thread.  The fix is to upgrade the filesystem or to have /tmp
-  be an ext2 filesystem.
-
-
-
-  13.4.  The compile fails with errors about conflicting types for
-  'open', 'dup', and 'waitpid'
-
-  This happens when you build in /usr/src/linux.  The UML build makes
-  the include/asm link point to include/asm-um.  /usr/include/asm points
-  to /usr/src/linux/include/asm, so when that link gets moved, files
-  which need to include the asm-i386 versions of headers get the
-  incompatible asm-um versions.  The fix is to move the include/asm link
-  back to include/asm-i386 and to do UML builds someplace else.
-
-
-
-  13.5.  UML doesn't work when /tmp is an NFS filesystem
-
-  This seems to be a similar situation with the ReiserFS problem above.
-  Some versions of NFS seems not to handle mmap correctly, which UML
-  depends on.  The workaround is have /tmp be a non-NFS directory.
-
-
-  13.6.  UML hangs on boot when compiled with gprof support
-
-  If you build UML with gprof support and, early in the boot, it does
-  this
-
-
-       kernel BUG at page_alloc.c:100!
-
-
-
-
-  you have a buggy gcc.  You can work around the problem by removing
-  UM_FASTCALL from CFLAGS in arch/um/Makefile-i386.  This will open up
-  another bug, but that one is fairly hard to reproduce.
-
-
-
-  13.7.  syslogd dies with a SIGTERM on startup
-
-  The exact boot error depends on the distribution that you're booting,
-  but Debian produces this:
-
-
-       /etc/rc2.d/S10sysklogd: line 49:    93 Terminated
-       start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD
-
-
-
-
-  This is a syslogd bug.  There's a race between a parent process
-  installing a signal handler and its child sending the signal.  See
-  this uml-devel post <http://www.geocrawler.com/lists/3/Source-
-  Forge/709/0/6612801>  for the details.
-
-
-
-  13.8.  TUN/TAP networking doesn't work on a 2.4 host
-
-  There are a couple of problems which were
-  <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
-  out">  by Tim Robinson <timro at trkr dot net>
-
-  o  It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
-     The fix is to upgrade to something more recent and then read the
-     next item.
-
-  o  If you see
-
-
-       File descriptor in bad state
-
-
-
-  when you bring up the device inside UML, you have a header mismatch
-  between the original kernel and the upgraded one.  Make /usr/src/linux
-  point at the new headers.  This will only be a problem if you build
-  uml_net yourself.
-
-
-
-  13.9.  You can network to the host but not to other machines on the
-  net
-
-  If you can connect to the host, and the host can connect to UML, but
-  you cannot connect to any other machines, then you may need to enable
-  IP Masquerading on the host.  Usually this is only experienced when
-  using private IP addresses (192.168.x.x or 10.x.x.x) for host/UML
-  networking, rather than the public address space that your host is
-  connected to.  UML does not enable IP Masquerading, so you will need
-  to create a static rule to enable it:
-
-
-       host%
-       iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-
-
-
-
-  Replace eth0 with the interface that you use to talk to the rest of
-  the world.
-
-
-  Documentation on IP Masquerading, and SNAT, can be found at
-  www.netfilter.org  <http://www.netfilter.org> .
-
-
-  If you can reach the local net, but not the outside Internet, then
-  that is usually a routing problem.  The UML needs a default route:
-
-
-       UML#
-       route add default gw gateway IP
-
-
-
-
-  The gateway IP can be any machine on the local net that knows how to
-  reach the outside world.  Usually, this is the host or the local net-
-  work's gateway.
-
-
-  Occasionally, we hear from someone who can reach some machines, but
-  not others on the same net, or who can reach some ports on other
-  machines, but not others.  These are usually caused by strange
-  firewalling somewhere between the UML and the other box.  You track
-  this down by running tcpdump on every interface the packets travel
-  over and see where they disappear.  When you find a machine that takes
-  the packets in, but does not send them onward, that's the culprit.
-
-
-
-  13.10.  I have no root and I want to scream
-
-  Thanks to Birgit Wahlich for telling me about this strange one.  It
-  turns out that there's a limit of six environment variables on the
-  kernel command line.  When that limit is reached or exceeded, argument
-  processing stops, which means that the 'root=' argument that UML
-  usually adds is not seen.  So, the filesystem has no idea what the
-  root device is, so it panics.
-
-
-  The fix is to put less stuff on the command line.  Glomming all your
-  setup variables into one is probably the best way to go.
-
-
-
-  13.11.  UML build conflict between ptrace.h and ucontext.h
-
-  On some older systems, /usr/include/asm/ptrace.h and
-  /usr/include/sys/ucontext.h define the same names.  So, when they're
-  included together, the defines from one completely mess up the parsing
-  of the other, producing errors like:
-       /usr/include/sys/ucontext.h:47: parse error before
-       `10'
-
-
-
-
-  plus a pile of warnings.
-
-
-  This is a libc botch, which has since been fixed, and I don't see any
-  way around it besides upgrading.
-
-
-
-  13.12.  The UML BogoMips is exactly half the host's BogoMips
-
-  On i386 kernels, there are two ways of running the loop that is used
-  to calculate the BogoMips rating, using the TSC if it's there or using
-  a one-instruction loop.  The TSC produces twice the BogoMips as the
-  loop.  UML uses the loop, since it has nothing resembling a TSC, and
-  will get almost exactly the same BogoMips as a host using the loop.
-  However, on a host with a TSC, its BogoMips will be double the loop
-  BogoMips, and therefore double the UML BogoMips.
-
-
-
-  13.13.  When you run UML, it immediately segfaults
-
-  If the host is configured with the 2G/2G address space split, that's
-  why.  See ``UML on 2G/2G hosts''  for the details on getting UML to
-  run on your host.
-
-
-
-  13.14.  xterms appear, then immediately disappear
-
-  If you're running an up to date kernel with an old release of
-  uml_utilities, the port-helper program will not work properly, so
-  xterms will exit straight after they appear. The solution is to
-  upgrade to the latest release of uml_utilities.  Usually this problem
-  occurs when you have installed a packaged release of UML then compiled
-  your own development kernel without upgrading the uml_utilities from
-  the source distribution.
-
-
-
-  13.15.  Any other panic, hang, or strange behavior
-
-  If you're seeing truly strange behavior, such as hangs or panics that
-  happen in random places, or you try running the debugger to see what's
-  happening and it acts strangely, then it could be a problem in the
-  host kernel.  If you're not running a stock Linus or -ac kernel, then
-  try that.  An early version of the preemption patch and a 2.4.10 SuSE
-  kernel have caused very strange problems in UML.
-
-
-  Otherwise, let me know about it.  Send a message to one of the UML
-  mailing lists - either the developer list - user-mode-linux-devel at
-  lists dot sourceforge dot net (subscription info) or the user list -
-  user-mode-linux-user at lists dot sourceforge do net (subscription
-  info), whichever you prefer.  Don't assume that everyone knows about
-  it and that a fix is imminent.
-
-
-  If you want to be super-helpful, read ``Diagnosing Problems'' and
-  follow the instructions contained therein.
-  14.  Diagnosing Problems
-
-
-  If you get UML to crash, hang, or otherwise misbehave, you should
-  report this on one of the project mailing lists, either the developer
-  list - user-mode-linux-devel at lists dot sourceforge dot net
-  (subscription info) or the user list - user-mode-linux-user at lists
-  dot sourceforge dot net (subscription info).  When you do, it is
-  likely that I will want more information.  So, it would be helpful to
-  read the stuff below, do whatever is applicable in your case, and
-  report the results to the list.
-
-
-  For any diagnosis, you're going to need to build a debugging kernel.
-  The binaries from this site aren't debuggable.  If you haven't done
-  this before, read about ``Compiling the kernel and modules''  and
-  ``Kernel debugging''  UML first.
-
-
-  14.1.  Case 1 : Normal kernel panics
-
-  The most common case is for a normal thread to panic.  To debug this,
-  you will need to run it under the debugger (add 'debug' to the command
-  line).  An xterm will start up with gdb running inside it.  Continue
-  it when it stops in start_kernel and make it crash.  Now ^C gdb and
-
-
-  If the panic was a "Kernel mode fault", then there will be a segv
-  frame on the stack and I'm going to want some more information.  The
-  stack might look something like this:
-
-
-       (UML gdb)  backtrace
-       #0  0x1009bf76 in __sigprocmask (how=1, set=0x5f347940, oset=0x0)
-           at ../sysdeps/unix/sysv/linux/sigprocmask.c:49
-       #1  0x10091411 in change_sig (signal=10, on=1) at process.c:218
-       #2  0x10094785 in timer_handler (sig=26) at time_kern.c:32
-       #3  0x1009bf38 in __restore ()
-           at ../sysdeps/unix/sysv/linux/i386/sigaction.c:125
-       #4  0x1009534c in segv (address=8, ip=268849158, is_write=2, is_user=0)
-           at trap_kern.c:66
-       #5  0x10095c04 in segv_handler (sig=11) at trap_user.c:285
-       #6  0x1009bf38 in __restore ()
-
-
-
-
-  I'm going to want to see the symbol and line information for the value
-  of ip in the segv frame.  In this case, you would do the following:
-
-
-       (UML gdb)  i sym 268849158
-
-
-
-
-  and
-
-
-       (UML gdb)  i line *268849158
-
-
-
-
-  The reason for this is the __restore frame right above the segv_han-
-  dler frame is hiding the frame that actually segfaulted.  So, I have
-  to get that information from the faulting ip.
-
-
-  14.2.  Case 2 : Tracing thread panics
-
-  The less common and more painful case is when the tracing thread
-  panics.  In this case, the kernel debugger will be useless because it
-  needs a healthy tracing thread in order to work.  The first thing to
-  do is get a backtrace from the tracing thread.  This is done by
-  figuring out what its pid is, firing up gdb, and attaching it to that
-  pid.  You can figure out the tracing thread pid by looking at the
-  first line of the console output, which will look like this:
-
-
-       tracing thread pid = 15851
-
-
-
-
-  or by running ps on the host and finding the line that looks like
-  this:
-
-
-       jdike 15851 4.5 0.4 132568 1104 pts/0 S 21:34 0:05 ./linux [(tracing thread)]
-
-
-
-
-  If the panic was 'segfault in signals', then follow the instructions
-  above for collecting information about the location of the seg fault.
-
-
-  If the tracing thread flaked out all by itself, then send that
-  backtrace in and wait for our crack debugging team to fix the problem.
-
-
-  14.3.  Case 3 : Tracing thread panics caused by other threads
-
-  However, there are cases where the misbehavior of another thread
-  caused the problem.  The most common panic of this type is:
-
-
-       wait_for_stop failed to wait for  <pid>  to stop with  <signal number>
-
-
-
-
-  In this case, you'll need to get a backtrace from the process men-
-  tioned in the panic, which is complicated by the fact that the kernel
-  debugger is defunct and without some fancy footwork, another gdb can't
-  attach to it.  So, this is how the fancy footwork goes:
-
-  In a shell:
-
-
-       host% kill -STOP pid
-
-
-
-
-  Run gdb on the tracing thread as described in case 2 and do:
-
-
-       (host gdb)  call detach(pid)
-
-
-  If you get a segfault, do it again.  It always works the second time.
-
-  Detach from the tracing thread and attach to that other thread:
-
-
-       (host gdb)  detach
-
-
-
-
-
-
-       (host gdb)  attach pid
-
-
-
-
-  If gdb hangs when attaching to that process, go back to a shell and
-  do:
-
-
-       host%
-       kill -CONT pid
-
-
-
-
-  And then get the backtrace:
-
-
-       (host gdb)  backtrace
-
-
-
-
-
-  14.4.  Case 4 : Hangs
-
-  Hangs seem to be fairly rare, but they sometimes happen.  When a hang
-  happens, we need a backtrace from the offending process.  Run the
-  kernel debugger as described in case 1 and get a backtrace.  If the
-  current process is not the idle thread, then send in the backtrace.
-  You can tell that it's the idle thread if the stack looks like this:
-
-
-       #0  0x100b1401 in __libc_nanosleep ()
-       #1  0x100a2885 in idle_sleep (secs=10) at time.c:122
-       #2  0x100a546f in do_idle () at process_kern.c:445
-       #3  0x100a5508 in cpu_idle () at process_kern.c:471
-       #4  0x100ec18f in start_kernel () at init/main.c:592
-       #5  0x100a3e10 in start_kernel_proc (unused=0x0) at um_arch.c:71
-       #6  0x100a383f in signal_tramp (arg=0x100a3dd8) at trap_user.c:50
-
-
-
-
-  If this is the case, then some other process is at fault, and went to
-  sleep when it shouldn't have.  Run ps on the host and figure out which
-  process should not have gone to sleep and stayed asleep.  Then attach
-  to it with gdb and get a backtrace as described in case 3.
-
-
-
-
-
-
-  15.  Thanks
-
-
-  A number of people have helped this project in various ways, and this
-  page gives recognition where recognition is due.
-
-
-  If you're listed here and you would prefer a real link on your name,
-  or no link at all, instead of the despammed email address pseudo-link,
-  let me know.
-
-
-  If you're not listed here and you think maybe you should be, please
-  let me know that as well.  I try to get everyone, but sometimes my
-  bookkeeping lapses and I forget about contributions.
-
-
-  15.1.  Code and Documentation
-
-  Rusty Russell <rusty at linuxcare.com.au>  -
-
-  o  wrote the  HOWTO <http://user-mode-
-     linux.sourceforge.net/UserModeLinux-HOWTO.html>
-
-  o  prodded me into making this project official and putting it on
-     SourceForge
-
-  o  came up with the way cool UML logo <http://user-mode-
-     linux.sourceforge.net/uml-small.png>
-
-  o  redid the config process
-
-
-  Peter Moulder <reiter at netspace.net.au>  - Fixed my config and build
-  processes, and added some useful code to the block driver
-
-
-  Bill Stearns <wstearns at pobox.com>  -
-
-  o  HOWTO updates
-
-  o  lots of bug reports
-
-  o  lots of testing
-
-  o  dedicated a box (uml.ists.dartmouth.edu) to support UML development
-
-  o  wrote the mkrootfs script, which allows bootable filesystems of
-     RPM-based distributions to be cranked out
-
-  o  cranked out a large number of filesystems with said script
-
-
-  Jim Leu <jleu at mindspring.com>  - Wrote the virtual ethernet driver
-  and associated usermode tools
-
-  Lars Brinkhoff <http://lars.nocrew.org/>  - Contributed the ptrace
-  proxy from his own  project <http://a386.nocrew.org/> to allow easier
-  kernel debugging
-
-
-  Andrea Arcangeli <andrea at suse.de>  - Redid some of the early boot
-  code so that it would work on machines with Large File Support
-
-
-  Chris Emerson <http://www.chiark.greenend.org.uk/~cemerson/>  - Did
-  the first UML port to Linux/ppc
-
-
-  Harald Welte <laforge at gnumonks.org>  - Wrote the multicast
-  transport for the network driver
-
-
-  Jorgen Cederlof - Added special file support to hostfs
-
-
-  Greg Lonnon  <glonnon at ridgerun dot com>  - Changed the ubd driver
-  to allow it to layer a COW file on a shared read-only filesystem and
-  wrote the iomem emulation support
-
-
-  Henrik Nordstrom <http://hem.passagen.se/hno/>  - Provided a variety
-  of patches, fixes, and clues
-
-
-  Lennert Buytenhek - Contributed various patches, a rewrite of the
-  network driver, the first implementation of the mconsole driver, and
-  did the bulk of the work needed to get SMP working again.
-
-
-  Yon Uriarte - Fixed the TUN/TAP network backend while I slept.
-
-
-  Adam Heath - Made a bunch of nice cleanups to the initialization code,
-  plus various other small patches.
-
-
-  Matt Zimmerman - Matt volunteered to be the UML Debian maintainer and
-  is doing a real nice job of it.  He also noticed and fixed a number of
-  actually and potentially exploitable security holes in uml_net.  Plus
-  the occasional patch.  I like patches.
-
-
-  James McMechan - James seems to have taken over maintenance of the ubd
-  driver and is doing a nice job of it.
-
-
-  Chandan Kudige - wrote the umlgdb script which automates the reloading
-  of module symbols.
-
-
-  Steve Schmidtke - wrote the UML slirp transport and hostaudio drivers,
-  enabling UML processes to access audio devices on the host. He also
-  submitted patches for the slip transport and lots of other things.
-
-
-  David Coulson <http://davidcoulson.net>  -
-
-  o  Set up the usermodelinux.org <http://usermodelinux.org>  site,
-     which is a great way of keeping the UML user community on top of
-     UML goings-on.
-
-  o  Site documentation and updates
-
-  o  Nifty little UML management daemon  UMLd
-     <http://uml.openconsultancy.com/umld/>
-
-  o  Lots of testing and bug reports
-
-
-
-
-  15.2.  Flushing out bugs
-
-
-
-  o  Yuri Pudgorodsky
-
-  o  Gerald Britton
-
-  o  Ian Wehrman
-
-  o  Gord Lamb
-
-  o  Eugene Koontz
-
-  o  John H. Hartman
-
-  o  Anders Karlsson
-
-  o  Daniel Phillips
-
-  o  John Fremlin
-
-  o  Rainer Burgstaller
-
-  o  James Stevenson
-
-  o  Matt Clay
-
-  o  Cliff Jefferies
-
-  o  Geoff Hoff
-
-  o  Lennert Buytenhek
-
-  o  Al Viro
-
-  o  Frank Klingenhoefer
-
-  o  Livio Baldini Soares
-
-  o  Jon Burgess
-
-  o  Petru Paler
-
-  o  Paul
-
-  o  Chris Reahard
-
-  o  Sverker Nilsson
-
-  o  Gong Su
-
-  o  johan verrept
-
-  o  Bjorn Eriksson
-
-  o  Lorenzo Allegrucci
-
-  o  Muli Ben-Yehuda
-
-  o  David Mansfield
-
-  o  Howard Goff
-
-  o  Mike Anderson
-
-  o  John Byrne
-
-  o  Sapan J. Batia
-
-  o  Iris Huang
-
-  o  Jan Hudec
-
-  o  Voluspa
-
-
-
-
-  15.3.  Buglets and clean-ups
-
-
-
-  o  Dave Zarzycki
-
-  o  Adam Lazur
-
-  o  Boria Feigin
-
-  o  Brian J. Murrell
-
-  o  JS
-
-  o  Roman Zippel
-
-  o  Wil Cooley
-
-  o  Ayelet Shemesh
-
-  o  Will Dyson
-
-  o  Sverker Nilsson
-
-  o  dvorak
-
-  o  v.naga srinivas
-
-  o  Shlomi Fish
-
-  o  Roger Binns
-
-  o  johan verrept
-
-  o  MrChuoi
-
-  o  Peter Cleve
-
-  o  Vincent Guffens
-
-  o  Nathan Scott
-
-  o  Patrick Caulfield
-
-  o  jbearce
-
-  o  Catalin Marinas
-
-  o  Shane Spencer
-
-  o  Zou Min
-
-
-  o  Ryan Boder
-
-  o  Lorenzo Colitti
-
-  o  Gwendal Grignou
-
-  o  Andre' Breiler
-
-  o  Tsutomu Yasuda
-
-
-
-  15.4.  Case Studies
-
-
-  o  Jon Wright
-
-  o  William McEwan
-
-  o  Michael Richardson
-
-
-
-  15.5.  Other contributions
-
-
-  Bill Carr <Bill.Carr at compaq.com>  made the Red Hat mkrootfs script
-  work with RH 6.2.
-
-  Michael Jennings <mikejen at hevanet.com>  sent in some material which
-  is now gracing the top of the  index  page <http://user-mode-
-  linux.sourceforge.net/>  of this site.
-
-  SGI <http://www.sgi.com>  (and more specifically Ralf Baechle <ralf at
-  uni-koblenz.de> ) gave me an account on oss.sgi.com
-  <http://www.oss.sgi.com> .  The bandwidth there made it possible to
-  produce most of the filesystems available on the project download
-  page.
-
-  Laurent Bonnaud <Laurent.Bonnaud at inpg.fr>  took the old grotty
-  Debian filesystem that I've been distributing and updated it to 2.2.
-  It is now available by itself here.
-
-  Rik van Riel gave me some ftp space on ftp.nl.linux.org so I can make
-  releases even when Sourceforge is broken.
-
-  Rodrigo de Castro looked at my broken pte code and told me what was
-  wrong with it, letting me fix a long-standing (several weeks) and
-  serious set of bugs.
-
-  Chris Reahard built a specialized root filesystem for running a DNS
-  server jailed inside UML.  It's available from the download
-  <http://user-mode-linux.sourceforge.net/dl-sf.html>  page in the Jail
-  Filesystems section.
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Documentation/vm/conf.py b/Documentation/vm/conf.py
deleted file mode 100644 (file)
index 3b0b601..0000000
+++ /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'),
-]
index 7d90964..710ce1c 100644 (file)
@@ -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()
index c165d92..c824cd7 100644 (file)
@@ -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 (file)
index 33c5c31..0000000
+++ /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'),
-]
index 783569e..316e67a 100644 (file)
@@ -899,7 +899,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 +1194,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
@@ -2155,10 +2155,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
@@ -2269,10 +2271,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*
@@ -4190,7 +4194,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
@@ -4469,7 +4473,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 +4484,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>
@@ -6322,7 +6326,8 @@ 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
 
@@ -6339,7 +6344,7 @@ 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 +6377,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/
@@ -6822,13 +6827,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 +6854,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
@@ -8044,6 +8042,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>
@@ -8490,7 +8489,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 +8507,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 +8807,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*
@@ -8828,10 +8827,10 @@ 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
@@ -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
@@ -11144,6 +11143,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 +11282,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 +12138,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 +12395,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
@@ -13725,6 +13726,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 +13949,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 +14017,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>
@@ -16078,7 +16085,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
@@ -16854,7 +16861,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 +17130,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 +17179,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
@@ -17555,7 +17561,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
index 9be5834..1b23f95 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc4
 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
 
@@ -998,6 +1003,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 +1774,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
 # ===========================================================================
index c929bea..85710e0 100644 (file)
@@ -1535,7 +1535,6 @@ config DEBUG_LL_INCLUDE
                                 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_RCAR_GEN1_SCIF0
@@ -1575,7 +1574,6 @@ config DEBUG_UART_8250
 
 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
@@ -1700,7 +1698,6 @@ config DEBUG_UART_PHYS
                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_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \
                DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF1 || \
@@ -1717,7 +1714,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
@@ -1822,7 +1818,6 @@ config DEBUG_UART_VIRT
        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 || \
index 9159fa2..e10d9e9 100644 (file)
@@ -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,6 +911,7 @@ 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 \
@@ -919,6 +926,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 +934,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 +1123,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 +1272,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 +1282,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 \
index 0257576..2f6652e 100644 (file)
@@ -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;
        };
                >;
        };
 
-       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 */
 };
 
 &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>;
 /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 {
        };
 };
 
-&aes {
-       status = "okay";
-};
-
-&sham {
-       status = "okay";
-};
-
 &rtc {
        system-power-controller;
        clocks = <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>;
index ceecbfd..1fe3b56 100644 (file)
@@ -44,7 +44,6 @@
                regulator-name = "vwlan_fixed";
                gpio = <&gpio0 20 GPIO_ACTIVE_HIGH>; /* gpio0_20 */
                enable-active-high;
-               regulator-boot-off;
        };
 
        backlight {
index 556ed46..c9d88c9 100644 (file)
        };
 };
 
+&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 (file)
index 0000000..c054782
--- /dev/null
@@ -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";
+};
index c4521ed..682f729 100644 (file)
        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;
        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 {
 &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 {
 &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 (file)
index 0000000..b1e10f0
--- /dev/null
@@ -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 (file)
index 0000000..aaa77a5
--- /dev/null
@@ -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";
+};
index 628195b..e9d714a 100644 (file)
                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 (file)
index 0000000..118eb8b
--- /dev/null
@@ -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 100755 (executable)
index 0000000..e55cc45
--- /dev/null
@@ -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"
+
index caac895..25bc0e1 100644 (file)
                #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>;
        status = "okay";
 };
 
+&sdmmc {
+       status = "okay";
+};
+
+&sdhci1 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sd2_default>;
+};
+
 #include "ibm-power9-dual.dtsi"
index dd4b0b1..e465cda 100644 (file)
                                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;
index 5b1ca26..f360b6c 100644 (file)
                                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;
                groups = "SDA2";
        };
 
+       pinctrl_sgpm_default: sgpm_default {
+               function = "SGPM";
+               groups = "SGPM";
+       };
+
        pinctrl_sgps1_default: sgps1_default {
                function = "SGPS1";
                groups = "SGPS1";
index 18d0ae4..0faae89 100644 (file)
        };
 
        mdio-bus-mux {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
                /* BIT(9) = 1 => external mdio */
                mdio_ext: mdio@200 {
                        reg = <0x200>;
index a0c270f..da07647 100644 (file)
 
        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>;
index 462a540..dfceb15 100644 (file)
                        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 */
                        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 */
                        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 */
                        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 */
                        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 */
                        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 */
                        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 */
                        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 */
                        buck9_reg: BUCK9 {
                                regulator-name = "vddf28_emmc";
                                regulator-min-microvolt = <750000>;
-                               regulator-max-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
                                op_mode = <1>; /* Normal Mode */
                        };
                };
index d5e0392..30f6f5c 100644 (file)
                        clock-names = "sata", "sclk_sata";
                        phys = <&sata_phy>;
                        phy-names = "sata-phy";
+                       ports-implemented = <0x1>;
                        status = "disabled";
                };
 
index 55d4dbf..7d51e0f 100644 (file)
                        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 {
                        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>;
index 57d3b31..de639ee 100644 (file)
 &mfc {
        compatible = "samsung,mfc-v8";
 };
+
+&soc {
+       cam_pd: power-domain@10045100 {
+               compatible = "samsung,exynos4210-pd";
+               reg = <0x10045100 0x20>;
+               #power-domain-cells = <0>;
+               label = "CAM";
+       };
+};
index f4535d6..521714f 100644 (file)
@@ -20,7 +20,7 @@
        };
 
        chosen {
-               bootargs = "console=ttyS0,19200n8";
+               bootargs = "console=ttyS0,19200n8 root=/dev/mtdblock3 rw rootfstype=squashfs,jffs2 rootwait";
                stdout-path = &uart0;
        };
 
                        /* 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>;
                        };
                };
 
index 2bb9534..a98af03 100644 (file)
@@ -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 {
                        /* 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";
                                        };
                                };
                                /*
index dbecd6d..7d4301b 100644 (file)
@@ -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>;
index ad2f7e8..80a7f96 100644 (file)
@@ -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>;
index d60d8f4..24027a1 100644 (file)
@@ -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>;
index f8544a9..05cccd1 100644 (file)
@@ -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>;
index 087c6e2..6f1e8ce 100644 (file)
 
        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>;
index 84fc8df..9c3ec82 100644 (file)
 
        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>;
index 5e5e282..0cd75da 100644 (file)
 
        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>;
index 5606f41..bf883e4 100644 (file)
 
        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>;
index 10acc53..719ed5c 100644 (file)
@@ -54,7 +54,8 @@
        };
 
        panel {
-               compatible = "edt,etm070080dh6";
+               compatible = "edt,etm0700g0dh6";
+               pinctrl-0 = <&pinctrl_display_gpio>;
                enable-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>;
 
                port {
index 1beac22..019dda6 100644 (file)
        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 {
index 7a85116..2418cf8 100644 (file)
        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";
index 82802f8..d434868 100644 (file)
        };
 
        rtc@51 {
-               compatible = "nxp,rtc8564";
+               compatible = "epson,rtc8564";
                reg = <0x51>;
        };
 
index 50d9a98..2cfb411 100644 (file)
                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";
                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 {
                                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
                        >;
                };
 
                        >;
                };
 
+               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
        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>;
index 4b80193..e6b4b85 100644 (file)
 
                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>;
                        };
 
                        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>,
index b36fc01..3a96b55 100644 (file)
                };
        };
 
-       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";
                        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>;
index b0a77ff..13c7ba7 100644 (file)
                };
        };
 
-       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>;
                        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>;
                                        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>,
                        };
 
                        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>,
                                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>,
index bb25add..531a52c 100644 (file)
                };
        };
 
-       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>;
                        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>;
                                         <&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";
                        };
 
index cbe61b6..c2a9dd5 100644 (file)
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index 21ddd35..9f63706 100644 (file)
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index b26d4f5..cc9adce 100644 (file)
 };
 
 &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 (file)
index 0000000..5bad296
--- /dev/null
@@ -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 (file)
index 0000000..0205fd5
--- /dev/null
@@ -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 (file)
index 0000000..a896b23
--- /dev/null
@@ -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
+               >;
+       };
+};
index 0e59ee5..8ecdb9a 100644 (file)
@@ -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>;
                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";
 &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-pcl063.dtsi
deleted file mode 100644 (file)
index fc29974..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2016 PHYTEC Messtechnik GmbH
- * Author: Christian Hemp <c.hemp@phytec.de>
- */
-
-#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";
-       compatible = "phytec,imx6ul-pcl063", "fsl,imx6ul";
-
-       chosen {
-               stdout-path = &uart1;
-       };
-
-       /*
-        * Set the minimum memory size here and
-        * let the bootloader set the real size.
-        */
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x8000000>;
-       };
-
-       gpio_leds_som: leds {
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_gpioleds_som>;
-               compatible = "gpio-leds";
-
-               led_green {
-                       label = "phycore:green";
-                       gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "heartbeat";
-               };
-       };
-};
-
-&fec1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet1>;
-       phy-mode = "rmii";
-       phy-handle = <&ethphy0>;
-       status = "okay";
-
-       mdio: mdio {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               ethphy0: 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";
-               };
-       };
-};
-
-&gpmi {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_gpmi_nand>;
-       nand-on-flash-bbt;
-       status = "okay";
-};
-
-&i2c1 {
-       pinctrl-names = "default";
-       pinctrl-0 =<&pinctrl_i2c1>;
-       clock-frequency = <100000>;
-       status = "okay";
-
-       eeprom@52 {
-               compatible = "catalyst,24c32", "atmel,24c32";
-               reg = <0x52>;
-       };
-};
-
-&snvs_poweroff {
-       status = "okay";
-};
-
-&uart1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1>;
-       status = "okay";
-};
-
-&iomuxc {
-       pinctrl_enet1: enet1grp {
-               fsl,pins = <
-                       MX6UL_PAD_GPIO1_IO07__ENET1_MDC         0x1b0b0
-                       MX6UL_PAD_GPIO1_IO06__ENET1_MDIO        0x1b0b0
-                       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_GPIO1_IO02__GPIO1_IO02        0x17059
-               >;
-       };
-
-       pinctrl_gpioleds_som: gpioledssomgrp {
-               fsl,pins = <MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04  0x0b0b0>;
-       };
-
-       pinctrl_gpmi_nand: gpminandgrp {
-               fsl,pins = <
-                       MX6UL_PAD_NAND_CLE__RAWNAND_CLE         0x0b0b1
-                       MX6UL_PAD_NAND_ALE__RAWNAND_ALE         0x0b0b1
-                       MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B       0x0b0b1
-                       MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0x0b000
-                       MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B     0x0b0b1
-                       MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B       0x0b0b1
-                       MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B       0x0b0b1
-                       MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00   0x0b0b1
-                       MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01   0x0b0b1
-                       MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02   0x0b0b1
-                       MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03   0x0b0b1
-                       MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04   0x0b0b1
-                       MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05   0x0b0b1
-                       MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06   0x0b0b1
-                       MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07   0x0b0b1
-               >;
-       };
-
-       pinctrl_i2c1: i2cgrp {
-               fsl,pins = <
-                       MX6UL_PAD_UART4_TX_DATA__I2C1_SCL       0x4001b8b0
-                       MX6UL_PAD_UART4_RX_DATA__I2C1_SDA       0x4001b8b0
-               >;
-       };
-
-       pinctrl_uart1: uart1grp {
-               fsl,pins = <
-                       MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX   0x1b0b1
-                       MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX   0x1b0b1
-               >;
-       };
-
-};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi b/arch/arm/boot/dts/imx6ul-phytec-peb-eval-01.dtsi
deleted file mode 100644 (file)
index e2f38f3..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2016 PHYTEC Messtechnik
- * Author: Christian Hemp <c.hemp@phytec.de>
- */
-
-#include <dt-bindings/input/input.h>
-
-/ {
-       gpio_keys: gpio-keys {
-               compatible = "gpio-key";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_gpio_keys>;
-               status = "disabled";
-
-               power {
-                       label = "Power Button";
-                       gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_POWER>;
-                       wakeup-source;
-               };
-       };
-
-       user_leds: 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";
-               };
-
-               led_red {
-                       gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-on";
-               };
-       };
-};
-
-&iomuxc {
-       pinctrl_gpio_keys: gpio_keysgrp {
-               fsl,pins = <
-                       MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00      0x79
-               >;
-       };
-
-       pinctrl_user_leds: user_ledsgrp {
-               fsl,pins = <
-                       MX6UL_PAD_JTAG_MOD__GPIO1_IO10          0x79
-                       MX6UL_PAD_GPIO1_IO01__GPIO1_IO01        0x79
-               >;
-       };
-};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts b/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts
deleted file mode 100644 (file)
index b6a1407..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2016 PHYTEC Messtechnik GmbH
- * Author: Christian Hemp <c.hemp@phytec.de>
- */
-
-/dts-v1/;
-#include "imx6ul-phytec-pcl063.dtsi"
-#include "imx6ul-phytec-phyboard-segin.dtsi"
-#include "imx6ul-phytec-peb-eval-01.dtsi"
-
-/ {
-       model = "Phytec phyBOARD-Segin i.MX6 UltraLite Full Featured";
-       compatible = "phytec,imx6ul-pbacd10", "phytec,imx6ul-pcl063", "fsl,imx6ul";
-};
-
-&adc1 {
-       status = "okay";
-};
-
-&can1 {
-       status = "okay";
-};
-
-&tlv320 {
-       status = "okay";
-};
-
-&ecspi3 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_ecspi3>;
-       cs-gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
-       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";
-};
-
-&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-phyboard-segin.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin.dtsi
deleted file mode 100644 (file)
index 7bf439a..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2016 PHYTEC Messtechnik GmbH
- * Author: Christian Hemp <c.hemp@phytec.de>
- */
-
-/ {
-       model = "Phytec phyBOARD-Segin i.MX6 UltraLite";
-       compatible = "phytec,imx6ul-pbacd-10", "phytec,imx6ul-pcl063", "fsl,imx6ul";
-
-       aliases {
-               rtc0 = &i2c_rtc;
-               rtc1 = &snvs_rtc;
-       };
-
-       reg_sound_1v8: regulator-1v8 {
-               compatible = "regulator-fixed";
-               regulator-name = "i2s-audio-1v8";
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-               status = "disabled";
-       };
-
-       reg_sound_3v3: regulator-3v3 {
-               compatible = "regulator-fixed";
-               regulator-name = "i2s-audio-3v3";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               status = "disabled";
-       };
-
-       reg_can1_en: regulator-can1 {
-               compatible = "regulator-fixed";
-               pinctrl-names = "default";
-               pinctrl-0 = <&princtrl_flexcan1_en>;
-               regulator-name = "Can";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
-               enable-active-high;
-               status = "disabled";
-       };
-
-       reg_adc1_vref_3v3: regulator-vref-3v3 {
-               compatible = "regulator-fixed";
-               regulator-name = "vref-3v3";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-       };
-
-       sound: sound {
-               compatible = "simple-audio-card";
-               simple-audio-card,name = "phyBOARD-Segin-TLV320AIC3007";
-               simple-audio-card,format = "i2s";
-               simple-audio-card,bitclock-master = <&dailink_master>;
-               simple-audio-card,frame-master = <&dailink_master>;
-               simple-audio-card,widgets =
-                       "Line", "Line In",
-                       "Line", "Line Out",
-                       "Speaker", "Speaker";
-               simple-audio-card,routing =
-                       "Line Out", "LLOUT",
-                       "Line Out", "RLOUT",
-                       "Speaker", "SPOP",
-                       "Speaker", "SPOM",
-                       "LINE1L", "Line In",
-                       "LINE1R", "Line In";
-               status = "disabled";
-
-               simple-audio-card,cpu {
-                       sound-dai = <&sai2>;
-               };
-
-               dailink_master: simple-audio-card,codec {
-                       sound-dai = <&tlv320>;
-                       clocks = <&clks IMX6UL_CLK_SAI2>;
-               };
-       };
-
-};
-
-&adc1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_adc1>;
-       vref-supply = <&reg_adc1_vref_3v3>;
-       /*
-        * driver can not separate a specific channel so we request 4 channels
-        * here - we need only the fourth channel
-        */
-       num-channels = <4>;
-       status = "disabled";
-};
-
-&can1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_flexcan1>;
-       xceiver-supply = <&reg_can1_en>;
-       status = "disabled";
-};
-
-&clks {
-       assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
-       assigned-clock-rates = <786432000>;
-};
-
-&fec2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet2>;
-       phy-mode = "rmii";
-       phy-handle = <&ethphy1>;
-       status = "disabled";
-};
-
-&i2c1 {
-       tlv320: codec@18 {
-               compatible = "ti,tlv320aic3007";
-               #sound-dai-cells = <0>;
-               reg = <0x18>;
-               AVDD-supply = <&reg_sound_3v3>;
-               IOVDD-supply = <&reg_sound_3v3>;
-               DRVDD-supply = <&reg_sound_3v3>;
-               DVDD-supply = <&reg_sound_1v8>;
-               status = "disabled";
-       };
-
-       stmpe: touchscreen@44 {
-               compatible = "st,stmpe811";
-               reg = <0x44>;
-               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
-               interrupt-parent = <&gpio5>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_stmpe>;
-               status = "disabled";
-
-               touchscreen {
-                       compatible = "st,stmpe-ts";
-                       st,sample-time = <4>;
-                       st,mod-12b = <1>;
-                       st,ref-sel = <0>;
-                       st,adc-freq = <1>;
-                       st,ave-ctrl = <1>;
-                       st,touch-det-delay = <2>;
-                       st,settling = <2>;
-                       st,fraction-z = <7>;
-                       st,i-drive = <1>;
-                       touchscreen-inverted-x = <1>;
-                       touchscreen-inverted-y = <1>;
-               };
-       };
-
-       i2c_rtc: rtc@68 {
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_rtc_int>;
-               compatible = "microcrystal,rv4162";
-               reg = <0x68>;
-               interrupt-parent = <&gpio5>;
-               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
-               status = "disabled";
-       };
-};
-
-&mdio {
-       ethphy1: ethernet-phy@2 {
-               reg = <2>;
-               micrel,led-mode = <1>;
-               clocks = <&clks IMX6UL_CLK_ENET2_REF>;
-               clock-names = "rmii-ref";
-       };
-};
-
-&pwm3 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_pwm3>;
-       status = "disabled";
-};
-
-&sai2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_sai2>;
-       assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
-                       <&clks IMX6UL_CLK_SAI2>;
-       assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
-       assigned-clock-rates = <0>, <19200000>;
-       fsl,sai-mclk-direction-output;
-       status = "disabled";
-};
-
-&uart5 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart5>;
-       uart-has-rtscts;
-       status = "disabled";
-};
-
-&usbotg1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usb_otg1_id>;
-       dr_mode = "otg";
-       status = "disabled";
-};
-
-&usbotg2 {
-       dr_mode = "host";
-       disable-over-current;
-       status = "disabled";
-};
-
-&usdhc1 {
-       pinctrl-names = "default", "state_100mhz", "state_200mhz";
-       pinctrl-0 = <&pinctrl_usdhc1>;
-       pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
-       pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
-       cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
-       no-1-8-v;
-       keep-power-in-suspend;
-       wakeup-source;
-       status = "disabled";
-};
-
-&iomuxc {
-       pinctrl_adc1: adc1grp {
-               fsl,pins = <
-                       MX6UL_PAD_GPIO1_IO03__GPIO1_IO03        0xb0
-               >;
-       };
-
-       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
-               >;
-       };
-
-       pinctrl_flexcan1: flexcan1 {
-               fsl,pins = <
-                       MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX      0x0b0b0
-                       MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX      0x0b0b0
-               >;
-       };
-
-       princtrl_flexcan1_en: flexcan1engrp {
-               fsl,pins = <
-                       MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02      0x17059
-               >;
-       };
-
-       pinctrl_pwm3: pwm3grp {
-               fsl,pins = <
-                       MX6UL_PAD_GPIO1_IO04__PWM3_OUT  0x0b0b0
-               >;
-       };
-
-       pinctrl_rtc_int: rtcintgrp {
-               fsl,pins = <
-                       MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01      0x17059
-               >;
-       };
-
-       pinctrl_sai2: sai2grp {
-               fsl,pins = <
-                       MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK        0x17088
-                       MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC        0x17088
-                       MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA     0x11088
-                       MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA        0x11088
-                       MX6UL_PAD_JTAG_TMS__SAI2_MCLK           0x17088
-               >;
-       };
-
-       pinctrl_stmpe: stmpegrp {
-               fsl,pins = <
-                       MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03      0x17059
-               >;
-       };
-
-       pinctrl_uart5: uart5grp {
-               fsl,pins = <
-                       MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX   0x1b0b1
-                       MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX   0x1b0b1
-                       MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS     0x1b0b1
-                       MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS     0x1b0b1
-               >;
-       };
-
-       pinctrl_usb_otg1_id: usbotg1idgrp {
-               fsl,pins = <
-                       MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID    0x17059
-               >;
-       };
-
-       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       0x17059
-               >;
-       };
-
-       pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
-               fsl,pins = <
-                       MX6UL_PAD_SD1_CMD__USDHC1_CMD           0x170b9
-                       MX6UL_PAD_SD1_CLK__USDHC1_CLK           0x100b9
-                       MX6UL_PAD_SD1_DATA0__USDHC1_DATA0       0x170b9
-                       MX6UL_PAD_SD1_DATA1__USDHC1_DATA1       0x170b9
-                       MX6UL_PAD_SD1_DATA2__USDHC1_DATA2       0x170b9
-                       MX6UL_PAD_SD1_DATA3__USDHC1_DATA3       0x170b9
-               >;
-       };
-
-       pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
-               fsl,pins = <
-                       MX6UL_PAD_SD1_CMD__USDHC1_CMD           0x170f9
-                       MX6UL_PAD_SD1_CLK__USDHC1_CLK           0x100f9
-                       MX6UL_PAD_SD1_DATA0__USDHC1_DATA0       0x170f9
-                       MX6UL_PAD_SD1_DATA1__USDHC1_DATA1       0x170f9
-                       MX6UL_PAD_SD1_DATA2__USDHC1_DATA2       0x170f9
-                       MX6UL_PAD_SD1_DATA3__USDHC1_DATA3       0x170f9
-               >;
-       };
-};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi
new file mode 100644 (file)
index 0000000..41f3b7f
--- /dev/null
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+       model = "PHYTEC phyCORE-i.MX6 UltraLite";
+       compatible = "phytec,imx6ul-pcl063", "fsl,imx6ul";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       /*
+        * Set the minimum memory size here and
+        * let the bootloader set the real size.
+        */
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x8000000>;
+       };
+
+       gpio_leds_som: leds {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpioleds_som>;
+               compatible = "gpio-leds";
+
+               phycore-green {
+                       gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
+
+&fec1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet1>;
+       phy-mode = "rmii";
+       phy-handle = <&ethphy1>;
+       status = "disabled";
+
+       mdio: mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               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";
+               };
+       };
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       nand-on-flash-bbt;
+       status = "disabled";
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       clock-frequency = <100000>;
+       status = "okay";
+
+       eeprom@52 {
+               compatible = "catalyst,24c32", "atmel,24c32";
+               reg = <0x52>;
+       };
+};
+
+&snvs_poweroff {
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       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         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      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
+               >;
+       };
+
+       pinctrl_gpioleds_som: gpioledssomgrp {
+               fsl,pins = <MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04  0x0b0b0>;
+       };
+
+       pinctrl_gpmi_nand: gpminandgrp {
+               fsl,pins = <
+                       MX6UL_PAD_NAND_CLE__RAWNAND_CLE         0x0b0b1
+                       MX6UL_PAD_NAND_ALE__RAWNAND_ALE         0x0b0b1
+                       MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B       0x0b0b1
+                       MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0x0b000
+                       MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B     0x0b0b1
+                       MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B       0x0b0b1
+                       MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B       0x0b0b1
+                       MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00   0x0b0b1
+                       MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01   0x0b0b1
+                       MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02   0x0b0b1
+                       MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03   0x0b0b1
+                       MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04   0x0b0b1
+                       MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05   0x0b0b1
+                       MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06   0x0b0b1
+                       MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07   0x0b0b1
+               >;
+       };
+
+       pinctrl_i2c1: i2cgrp {
+               fsl,pins = <
+                       MX6UL_PAD_UART4_TX_DATA__I2C1_SCL       0x4001b8b0
+                       MX6UL_PAD_UART4_RX_DATA__I2C1_SDA       0x4001b8b0
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX   0x1b0b1
+                       MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX   0x1b0b1
+               >;
+       };
+
+       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-segin-ff-rdk-nand.dts b/arch/arm/boot/dts/imx6ul-phytec-segin-ff-rdk-nand.dts
new file mode 100644 (file)
index 0000000..699dfcb
--- /dev/null
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+/dts-v1/;
+#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 with NAND";
+       compatible = "phytec,imx6ul-pbacd10-nand", "phytec,imx6ul-pbacd10",
+                    "phytec,imx6ul-pcl063", "fsl,imx6ul";
+};
+
+&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/imx6ul-phytec-segin-peb-eval-01.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin-peb-eval-01.dtsi
new file mode 100644 (file)
index 0000000..2f3fd32
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 PHYTEC Messtechnik
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+#include <dt-bindings/input/input.h>
+
+/ {
+       gpio_keys: gpio-keys {
+               compatible = "gpio-key";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_keys>;
+               status = "disabled";
+
+               power {
+                       label = "Power Button";
+                       gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+                       wakeup-source;
+               };
+       };
+
+       user_leds: user-leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_user_leds>;
+               status = "disabled";
+
+               user-led1 {
+                       gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "gpio";
+                       default-state = "on";
+               };
+
+               user-led2 {
+                       gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "gpio";
+                       default-state = "on";
+               };
+       };
+};
+
+&iomuxc {
+       pinctrl_gpio_keys: gpio_keysgrp {
+               fsl,pins = <
+                       MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00      0x79
+               >;
+       };
+
+       pinctrl_user_leds: user_ledsgrp {
+               fsl,pins = <
+                       MX6UL_PAD_JTAG_MOD__GPIO1_IO10          0x79
+                       MX6UL_PAD_GPIO1_IO01__GPIO1_IO01        0x79
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi b/arch/arm/boot/dts/imx6ul-phytec-segin.dtsi
new file mode 100644 (file)
index 0000000..8d5f8dc
--- /dev/null
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 PHYTEC Messtechnik GmbH
+ * Author: Christian Hemp <c.hemp@phytec.de>
+ */
+
+/ {
+       model = "PHYTEC phyBOARD-Segin i.MX6 UltraLite";
+       compatible = "phytec,imx6ul-pbacd-10", "phytec,imx6ul-pcl063", "fsl,imx6ul";
+
+       aliases {
+               rtc0 = &i2c_rtc;
+               rtc1 = &snvs_rtc;
+       };
+
+       reg_sound_1v8: regulator-1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "i2s-audio-1v8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               status = "disabled";
+       };
+
+       reg_sound_3v3: regulator-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "i2s-audio-3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               status = "disabled";
+       };
+
+       reg_can1_en: regulator-can1 {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&princtrl_flexcan1_en>;
+               regulator-name = "Can";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+               status = "disabled";
+       };
+
+       reg_adc1_vref_3v3: regulator-vref-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "vref-3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       sound: sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "phyBOARD-Segin-TLV320AIC3007";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&dailink_master>;
+               simple-audio-card,frame-master = <&dailink_master>;
+               simple-audio-card,widgets =
+                       "Line", "Line In",
+                       "Line", "Line Out",
+                       "Speaker", "Speaker";
+               simple-audio-card,routing =
+                       "Line Out", "LLOUT",
+                       "Line Out", "RLOUT",
+                       "Speaker", "SPOP",
+                       "Speaker", "SPOM",
+                       "LINE1L", "Line In",
+                       "LINE1R", "Line In";
+               status = "disabled";
+
+               simple-audio-card,cpu {
+                       sound-dai = <&sai2>;
+               };
+
+               dailink_master: simple-audio-card,codec {
+                       sound-dai = <&tlv320>;
+                       clocks = <&clks IMX6UL_CLK_SAI2>;
+               };
+       };
+
+};
+
+&adc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_adc1>;
+       vref-supply = <&reg_adc1_vref_3v3>;
+       /*
+        * driver can not separate a specific channel so we request 4 channels
+        * here - we need only the fourth channel
+        */
+       num-channels = <4>;
+       status = "disabled";
+};
+
+&can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       xceiver-supply = <&reg_can1_en>;
+       status = "disabled";
+};
+
+&clks {
+       assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+       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 = <&ethphy2>;
+       status = "disabled";
+};
+
+&i2c1 {
+       tlv320: codec@18 {
+               compatible = "ti,tlv320aic3007";
+               #sound-dai-cells = <0>;
+               reg = <0x18>;
+               AVDD-supply = <&reg_sound_3v3>;
+               IOVDD-supply = <&reg_sound_3v3>;
+               DRVDD-supply = <&reg_sound_3v3>;
+               DVDD-supply = <&reg_sound_1v8>;
+               status = "disabled";
+       };
+
+       stmpe: touchscreen@44 {
+               compatible = "st,stmpe811";
+               reg = <0x44>;
+               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-parent = <&gpio5>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_stmpe>;
+               status = "disabled";
+
+               touchscreen {
+                       compatible = "st,stmpe-ts";
+                       st,sample-time = <4>;
+                       st,mod-12b = <1>;
+                       st,ref-sel = <0>;
+                       st,adc-freq = <1>;
+                       st,ave-ctrl = <1>;
+                       st,touch-det-delay = <2>;
+                       st,settling = <2>;
+                       st,fraction-z = <7>;
+                       st,i-drive = <1>;
+                       touchscreen-inverted-x = <1>;
+                       touchscreen-inverted-y = <1>;
+               };
+       };
+
+       i2c_rtc: rtc@68 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_rtc_int>;
+               compatible = "microcrystal,rv4162";
+               reg = <0x68>;
+               interrupt-parent = <&gpio5>;
+               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+               status = "disabled";
+       };
+};
+
+&mdio {
+       ethphy2: ethernet-phy@2 {
+               reg = <2>;
+               micrel,led-mode = <1>;
+               clocks = <&clks IMX6UL_CLK_ENET2_REF>;
+               clock-names = "rmii-ref";
+               status = "disabled";
+       };
+};
+
+&pwm3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm3>;
+       status = "disabled";
+};
+
+&sai2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sai2>;
+       assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+                       <&clks IMX6UL_CLK_SAI2>;
+       assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+       assigned-clock-rates = <0>, <19200000>;
+       fsl,sai-mclk-direction-output;
+       status = "disabled";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       uart-has-rtscts;
+       status = "disabled";
+};
+
+&usbotg1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usb_otg1_id>;
+       dr_mode = "otg";
+       status = "disabled";
+};
+
+&usbotg2 {
+       dr_mode = "host";
+       disable-over-current;
+       status = "disabled";
+};
+
+&usdhc1 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc1>;
+       pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+       cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+       no-1-8-v;
+       keep-power-in-suspend;
+       wakeup-source;
+       status = "disabled";
+};
+
+&iomuxc {
+       pinctrl_adc1: adc1grp {
+               fsl,pins = <
+                       MX6UL_PAD_GPIO1_IO03__GPIO1_IO03        0xb0
+               >;
+       };
+
+       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      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
+               >;
+       };
+
+       pinctrl_flexcan1: flexcan1 {
+               fsl,pins = <
+                       MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX      0x0b0b0
+                       MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX      0x0b0b0
+               >;
+       };
+
+       princtrl_flexcan1_en: flexcan1engrp {
+               fsl,pins = <
+                       MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02      0x17059
+               >;
+       };
+
+       pinctrl_pwm3: pwm3grp {
+               fsl,pins = <
+                       MX6UL_PAD_GPIO1_IO04__PWM3_OUT  0x0b0b0
+               >;
+       };
+
+       pinctrl_rtc_int: rtcintgrp {
+               fsl,pins = <
+                       MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01      0x17059
+               >;
+       };
+
+       pinctrl_sai2: sai2grp {
+               fsl,pins = <
+                       MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK        0x17088
+                       MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC        0x17088
+                       MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA     0x11088
+                       MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA        0x11088
+                       MX6UL_PAD_JTAG_TMS__SAI2_MCLK           0x17088
+               >;
+       };
+
+       pinctrl_stmpe: stmpegrp {
+               fsl,pins = <
+                       MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03      0x17059
+               >;
+       };
+
+       pinctrl_uart5: uart5grp {
+               fsl,pins = <
+                       MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX   0x1b0b1
+                       MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX   0x1b0b1
+                       MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS     0x1b0b1
+                       MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS     0x1b0b1
+               >;
+       };
+
+       pinctrl_usb_otg1_id: usbotg1idgrp {
+               fsl,pins = <
+                       MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID    0x17059
+               >;
+       };
+
+       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       0x17059
+               >;
+       };
+
+       pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+               fsl,pins = <
+                       MX6UL_PAD_SD1_CMD__USDHC1_CMD           0x170b9
+                       MX6UL_PAD_SD1_CLK__USDHC1_CLK           0x100b9
+                       MX6UL_PAD_SD1_DATA0__USDHC1_DATA0       0x170b9
+                       MX6UL_PAD_SD1_DATA1__USDHC1_DATA1       0x170b9
+                       MX6UL_PAD_SD1_DATA2__USDHC1_DATA2       0x170b9
+                       MX6UL_PAD_SD1_DATA3__USDHC1_DATA3       0x170b9
+               >;
+       };
+
+       pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+               fsl,pins = <
+                       MX6UL_PAD_SD1_CMD__USDHC1_CMD           0x170f9
+                       MX6UL_PAD_SD1_CLK__USDHC1_CLK           0x100f9
+                       MX6UL_PAD_SD1_DATA0__USDHC1_DATA0       0x170f9
+                       MX6UL_PAD_SD1_DATA1__USDHC1_DATA1       0x170f9
+                       MX6UL_PAD_SD1_DATA2__USDHC1_DATA2       0x170f9
+                       MX6UL_PAD_SD1_DATA3__USDHC1_DATA3       0x170f9
+               >;
+       };
+};
index 39eeedd..09f7ffa 100644 (file)
@@ -43,7 +43,7 @@
 };
 
 &i2c2 {
-       clock_frequency = <100000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
index de07357..6cd7d58 100644 (file)
@@ -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";
index 81d4b49..f008036 100644 (file)
                };
        };
 
-       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)>,
                        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>;
                                        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";
                                };
 
                                        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";
                                };
 
                                        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";
                                };
 
                                        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";
                                };
 
                                         <&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";
                        };
 
                                         <&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";
                        };
 
                                         <&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";
                                         <&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";
                        };
                                };
                        };
 
+                       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 (file)
index 0000000..56cd16e
--- /dev/null
@@ -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 (file)
index 0000000..9648d4e
--- /dev/null
@@ -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 (file)
index 0000000..656baf8
--- /dev/null
@@ -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 (file)
index 0000000..e168494
--- /dev/null
@@ -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 (file)
index 0000000..ff08d95
--- /dev/null
@@ -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 (file)
index 0000000..c1595fc
--- /dev/null
@@ -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
+               >;
+       };
+};
index 895fbde..917eb0b 100644 (file)
@@ -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 {
 };
 
 &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>,
        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>;
 
 &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 {
 
 &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 {
        status = "okay";
 };
 
-&snvs_pwrkey {
-       status = "disabled";
-};
-
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_ctrl1 &pinctrl_uart1_ctrl2>;
        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 */
                >;
        };
 
+       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
                >;
        };
 
+       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
                >;
        };
 
+       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 */
                >;
        };
 
                >;
        };
 
+       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
                >;
        };
 
+       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 */
index e615674..7646284 100644 (file)
@@ -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";
                #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 (file)
index 0000000..2b8d6cc
--- /dev/null
@@ -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
+               >;
+       };
+};
index 4a78ddc..39812c9 100644 (file)
        status = "disabled";
 };
 
-&snvs_pwrkey {
-       status = "disabled";
-};
-
 &iomuxc {
        pinctrl_ecspi1: ecspi1grp {
                fsl,pins = <
index 42528d2..9c8dd32 100644 (file)
                        <&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";
        };
 
index c1a4fff..710f850 100644 (file)
                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";
                                        <&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";
                        };
                };
index 992747a..6859a3a 100644 (file)
                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>;
                        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>;
                        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";
                };
 
                        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";
                };
 
index 96d239d..bed1dfe 100644 (file)
                 */
                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 {
        };
 };
 
+&mali {
+       mali-supply = <&vddee>;
+};
+
 &saradc {
        status = "okay";
        vref-supply = <&vcc_1v8>;
 
 &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 {
index bb27b34..6e39ad5 100644 (file)
                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 {
        };
 };
 
+&mali {
+       mali-supply = <&vddee>;
+};
+
 &saradc {
        status = "okay";
        vref-supply = <&vcc_1v8>;
 
 &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 {
index 86c4614..a24eccc 100644 (file)
                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
        cpu-supply = <&vcck>;
 };
 
+&efuse {
+       ethernet_mac_address: mac@1b4 {
+               reg = <0x1b4 0x6>;
+       };
+};
+
 &ethmac {
        status = "okay";
 
        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>;
        pinctrl-names = "default";
 };
 
+&mali {
+       mali-supply = <&vddee>;
+};
+
 &saradc {
        status = "okay";
        vref-supply = <&vcc_1v8>;
 
 &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 {
index fba2c70..099bf8e 100644 (file)
                        };
                };
 
+               pwm_d_pins: pwm-d {
+                       mux {
+                               groups = "pwm_d";
+                               function = "pwm_d";
+                               bias-disable;
+                       };
+               };
+
                uart_b0_pins: uart-b0 {
                        mux {
                                groups = "uart_tx_b0",
                 <&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 (file)
index 0000000..3621b7d
--- /dev/null
@@ -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 (file)
index 0000000..9608bc2
--- /dev/null
@@ -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";
+               };
+       };
+};
index c53f427..41744cc 100644 (file)
@@ -8,7 +8,11 @@
 /include/ "nspire.dtsi"
 
 &lcd {
-       lcd-type = "classic";
+       port {
+               clcd_pads: endpoint {
+                       remote-endpoint = <&panel_in>;
+               };
+       };
 };
 
 &fast_timer {
                        #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";
        };
index da95c37..0c16b04 100644 (file)
@@ -9,7 +9,11 @@
 /include/ "nspire.dtsi"
 
 &lcd {
-       lcd-type = "cx";
+       port {
+               clcd_pads: endpoint {
+                       remote-endpoint = <&panel_in>;
+               };
+       };
 };
 
 &fast_timer {
                        };
                };
        };
+
+       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";
        };
index c35fd66..d9a0fd7 100644 (file)
                        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 {
index b295f6f..d01fc87 100644 (file)
                reg = <0x80000000 0x20000000>; /* 512 MB */
        };
 
+       chosen {
+               stdout-path = &uart3;
+       };
+
        aliases {
                display0 = &lcd;
                display1 = &tv0;
index 5441e9f..6681d45 100644 (file)
@@ -41,7 +41,6 @@
                regulator-name = "VWLAN";
                gpio = <&gpio2 3 GPIO_ACTIVE_HIGH>; /* gpio 35 */
                enable-active-high;
-               regulator-boot-off;
        };
 
        leds {
index 56cb10b..51806c7 100644 (file)
                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";
index 3ff2592..ebf5b7c 100644 (file)
                         <&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";
        };
 
                         <&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";
        };
 
index 0290ea4..c776321 100644 (file)
                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 (file)
index 0000000..679fc2b
--- /dev/null
@@ -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";
+};
index 8204407..2afd686 100644 (file)
@@ -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>;
index 2935768..81e4e95 100644 (file)
                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 {
 
 &saradc {
        vref-supply = <&vcc18_ldo1>;
-       status ="okay";
+       status = "okay";
 };
 
 &sdmmc {
 };
 
 &usb_otg {
-       status= "okay";
+       status = "okay";
 };
 
 &vopb {
index 1cadb52..ffb60f8 100644 (file)
@@ -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"
 
 / {
                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";
                };
        };
 
-       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";
        };
 };
 
-&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>;
 
        };
 };
 
-&vopl {
-       status = "okay";
-};
-
-&vopl_mmu {
-       status = "okay";
-};
-
 &pinctrl {
        pinctrl-0 = <
                /* Common for sleep and wake, but no owners */
                &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 (file)
index 0000000..b12e061
--- /dev/null
@@ -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 (file)
index 0000000..9a0f550
--- /dev/null
@@ -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>;
+               };
+       };
+};
index fcd1191..8038620 100644 (file)
                     "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 {
                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 {
 };
 
 &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>;
                };
        };
 
-       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>;
index 164561f..a6ee44f 100644 (file)
                     "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 {
        };
 };
 
+&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";
 };
 
 &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>;
                };
        };
 
-       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>;
index 9008e70..55955b0 100644 (file)
                     "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";
                        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 {
 
 &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 {
 };
 
 &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>;
                };
        };
 
-       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>;
index 9b6f4d9..f420499 100644 (file)
        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 {
        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>;
index 9b140db..2f2989b 100644 (file)
                     "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 {
        temperature = <90000>;
 };
 
-&panel {
-       power-supply= <&panel_regulator>;
-};
-
 &rk808 {
        pinctrl-names = "default";
        pinctrl-0 = <&pmic_int_l>;
 };
 
 &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>;
                };
        };
 
-       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 (file)
index 0000000..2755720
--- /dev/null
@@ -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>;
+               };
+       };
+};
index 8fc8eac..7525e3d 100644 (file)
                        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.
index ec19664..4f3993c 100644 (file)
@@ -85,6 +85,7 @@
                                clocks = <&l4_main_clk>;
                                clock-names = "apb_pclk";
                                resets = <&rst DMA_RESET>;
+                               reset-names = "dma";
                        };
                };
 
 
                nand0: nand@ff900000 {
                        #address-cells = <0x1>;
-                       #size-cells = <0x1>;
+                       #size-cells = <0x0>;
                        compatible = "altr,socfpga-denali-nand";
                        reg = <0xff900000 0x100000>,
                              <0xffb80000 0x10000>;
index a0a6d85..2a86e72 100644 (file)
@@ -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";
                        };
                };
 
 
                nand: nand@ffb90000 {
                        #address-cells = <1>;
-                       #size-cells = <1>;
+                       #size-cells = <0>;
                        compatible = "altr,socfpga-denali-nand";
                        reg = <0xffb90000 0x72000>,
                              <0xffb80000 0x10000>;
                        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";
                };
 
index e36e0a0..9bd9e04 100644 (file)
@@ -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>;
+               };
        };
 };
index 355b3db..a060718 100644 (file)
 
                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 {
                        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>;
                };
        };
 };
index b1a3113..90dcbc3 100644 (file)
@@ -92,7 +92,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>;
                };
 
                replicator {
-                       compatible = "arm,coresight-replicator";
+                       compatible = "arm,coresight-static-replicator";
                        clocks = <&prcmu_clk PRCMU_APEATCLK>;
                        clock-names = "atclk";
 
                        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";
+                               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>;
                        };
 
                        db8500-prcmu-regulators {
index b17998f..e32d0c3 100644 (file)
@@ -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>;
                };
 
                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 {
index 04066f9..41ed21a 100644 (file)
                 */
                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>;
 
                /*
index 3428290..064e8ab 100644 (file)
                        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 {
                                        /*
index 73ea84d..ba08624 100644 (file)
                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 {
 &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>;
index 4a49544..5c8a826 100644 (file)
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
index a25b700..d26f93f 100644 (file)
@@ -94,6 +94,7 @@
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                };
index ab78ad5..e4d3c58 100644 (file)
@@ -87,6 +87,7 @@
 };
 
 &adc_12 {
+       vdda-supply = <&vdda>;
        vref-supply = <&vdda>;
        status = "okay";
        adc1: adc@0 {
index df64701..e4a0d51 100644 (file)
@@ -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";
                        };
 
                                reg = <0x6000 0x400>;
                                clocks = <&rcc GPIOG>;
                                st,bank-name = "GPIOG";
-                               ngpios = <16>;
-                               gpio-ranges = <&pinctrl 0 96 16>;
                                status = "disabled";
                        };
 
                                reg = <0x7000 0x400>;
                                clocks = <&rcc GPIOH>;
                                st,bank-name = "GPIOH";
-                               ngpios = <16>;
-                               gpio-ranges = <&pinctrl 0 112 16>;
                                status = "disabled";
                        };
 
                                reg = <0x8000 0x400>;
                                clocks = <&rcc GPIOI>;
                                st,bank-name = "GPIOI";
-                               ngpios = <16>;
-                               gpio-ranges = <&pinctrl 0 128 16>;
                                status = "disabled";
                        };
 
                                reg = <0x9000 0x400>;
                                clocks = <&rcc GPIOJ>;
                                st,bank-name = "GPIOJ";
-                               ngpios = <16>;
-                               gpio-ranges = <&pinctrl 0 144 16>;
                                status = "disabled";
                        };
 
                                reg = <0xa000 0x400>;
                                clocks = <&rcc GPIOK>;
                                st,bank-name = "GPIOK";
-                               ngpios = <8>;
-                               gpio-ranges = <&pinctrl 0 160 8>;
                                status = "disabled";
                        };
 
                                };
                        };
 
+                       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 */
                                };
                        };
 
-                       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 */
                                clocks = <&rcc GPIOZ>;
                                st,bank-name = "GPIOZ";
                                st,bank-ioport = <11>;
-                               ngpios = <8>;
-                               gpio-ranges = <&pinctrl_z 0 400 8>;
                                status = "disabled";
                        };
 
index f3f0e37..0615d1c 100644 (file)
                #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;
                        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 {
                        };
                };
        };
+
+       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 {
        };
 };
 
+&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";
 };
        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>;
index 4fe7f71..1d426ea 100644 (file)
                #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;
        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";
 };
index feb8f77..89d29b5 100644 (file)
 &dsi {
        #address-cells = <1>;
        #size-cells = <0>;
+       phy-dsi-supply = <&reg18>;
        status = "okay";
 
        ports {
        };
 };
 
+&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>;
index 0c4e6eb..9b11654 100644 (file)
                };
        };
 
+       booster: regulator-booster {
+               compatible = "st,stm32mp1-booster";
+               st,syscfg = <&syscfg>;
+               status = "disabled";
+       };
+
        soc {
                compatible = "simple-bus";
                #address-cells = <1>;
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
                        timer@15 {
 
                        pwm {
                                compatible = "st,stm32-pwm";
+                               #pwm-cells = <3>;
                                status = "disabled";
                        };
 
                        clocks = <&rcc ADC12>, <&rcc ADC12_K>;
                        clock-names = "bus", "adc";
                        interrupt-controller;
+                       st,syscfg = <&syscfg>;
                        #interrupt-cells = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        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";
                        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";
+               };
+       };
 };
index 6c254ec..8692b11 100644 (file)
 };
 
 &emac {
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index 38a2c41..816d534 100644 (file)
@@ -68,7 +68,7 @@
 };
 
 &emac {
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index 7306c65..6ca02e8 100644 (file)
 };
 
 &emac {
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index cc988cc..47dea09 100644 (file)
@@ -80,7 +80,7 @@
 };
 
 &emac {
-       phy = <&phy0>;
+       phy-handle = <&phy0>;
        status = "okay";
 };
 
index 80ecd78..d4e319d 100644 (file)
@@ -58,7 +58,7 @@
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&emac_pins>;
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index 247fa27..8a7b4c5 100644 (file)
@@ -94,7 +94,7 @@
 };
 
 &emac {
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index 58ad2ad..a843e57 100644 (file)
 };
 
 &emac {
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index a8e537f..845f768 100644 (file)
 };
 
 &emac {
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index 0f1e781..83287b6 100644 (file)
 };
 
 &emac {
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index e88daa4..ce823c4 100644 (file)
                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 {
index 5340b41..7033a12 100644 (file)
@@ -98,7 +98,7 @@
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&emac_pa_pins>;
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index b5ee8fb..1f74ba1 100644 (file)
@@ -91,7 +91,7 @@
 &emac {
        pinctrl-names = "default";
        pinctrl-0 = <&emac_pd_pins>;
-       phy = <&phy1>;
+       phy-handle = <&phy1>;
        status = "okay";
 };
 
index fde559a..f9fc1c8 100644 (file)
@@ -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>;
index 2fb438c..cfb1efc 100644 (file)
                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 {
index c3d56dc..93a15ea 100644 (file)
 &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 {
        };
 };
 
+&mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v0>;
        bus-width = <4>;
index 09832b4..049e6ab 100644 (file)
 &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 {
        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>;
index 091eb2a..6cc8ccf 100644 (file)
 &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 {
        status = "okay";
 };
 
+&mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 6eafb63..a645c8f 100644 (file)
 &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 {
        status = "okay";
 };
 
+&mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_dcdc1>;
        bus-width = <4>;
index ca036f9..648f247 100644 (file)
 &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 {
        status = "okay";
 };
 
+&mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_dcdc1>;
        bus-width = <4>;
index dcddc33..bbeb743 100644 (file)
                                     <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 {
                        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 {
                };
 
                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>;
index 72a02c0..1d15e15 100644 (file)
 &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 {
        status = "okay";
 };
 
+&mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &ohci1 {
        status = "okay";
 };
index 4865c32..0af48e1 100644 (file)
 &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 {
        };
 };
 
+&mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_dcdc1>;
        bus-width = <4>;
index 8e724c5..708caee 100644 (file)
 &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 {
        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>;
index e2bfe00..32d5d45 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 4df9216..bb3987e 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 0176e9d..01ccff7 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 08e5a5a..b8203e4 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &ohci0 {
        status = "okay";
 };
index 99f531b..8c8dee6 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index fd0153f..3def2a3 100644 (file)
 &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 {
        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>;
index 5f1c4f5..358ed5f 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 7449aac..413505f 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index b90a760..946c272 100644 (file)
 &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>;
        };
index 3e170cf..17fa890 100644 (file)
        phy-mode = "rgmii";
        phy-supply = <&reg_gmac_3v3>;
        status = "okay";
-       /delete-property/#address-cells;
-       /delete-property/#size-cells;
 
        fixed-link {
                speed = <1000>;
index b8a1aaa..6bff9e7 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index f0e6a96..6f9c54b 100644 (file)
 &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 {
        };
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index c34a83f..230d62a 100644 (file)
 &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 {
        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>;
index e40dd47..2adbac8 100644 (file)
 &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 {
        };
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 56f451c..9ba6277 100644 (file)
 &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 {
        vref-supply = <&reg_vcc3v0>;
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 0dcba07..359bd0d 100644 (file)
 &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 {
        };
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 9628041..2e328d2 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 7b35326..d75b2e2 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 173b676..fce2f7f 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 14a88aa..cc8271d 100644 (file)
 &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 {
        status = "okay";
 };
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index f8475a3..3bfae98 100644 (file)
 &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 {
 
 #include "axp209.dtsi"
 
+&gmac_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        vmmc-supply = <&reg_vcc3v3>;
        bus-width = <4>;
index 9ad8e44..49380de 100644 (file)
                        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>;
                                function = "clk_out_b";
                        };
 
+                       /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",
                wdt: watchdog@1c20c90 {
                        compatible = "allwinner,sun4i-a10-wdt";
                        reg = <0x01c20c90 0x10>;
+                       interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                };
 
                rtc: rtc@1c20d00 {
                        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 {
index af2fa69..52eed0a 100644 (file)
                };
 
                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>;
                        compatible = "allwinner,sun6i-a31-wdt";
                        reg = <0x01c20ca0 0x20>;
                        interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                };
 
                pwm: pwm@1c21400 {
index 5659c63..51097c7 100644 (file)
@@ -63,7 +63,7 @@
 };
 
 &panel {
-       compatible = "bananapi,s070wv20-ct16", "simple-panel";
+       compatible = "bananapi,s070wv20-ct16";
 };
 
 &tcon0_out {
index ea299d3..fb92850 100644 (file)
                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";
 
        cpu-supply = <&reg_dcdc3>;
 };
 
+&de {
+       status = "okay";
+};
+
 &ehci0 {
        /* GL830 USB-to-SATA bridge here */
        status = "okay";
        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";
index ada6d08..523be66 100644 (file)
                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>;
                };
 
                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>;
                        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";
 
                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>;
index 6007d0c..bde0681 100644 (file)
                        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>;
                wdt: watchdog@1c20c90 {
                        compatible = "allwinner,sun4i-a10-wdt";
                        reg = <0x01c20c90 0x10>;
+                       interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                };
 
                uart0: serial@1c28000 {
                        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 (file)
index 0000000..d18192d
--- /dev/null
@@ -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 (file)
index 0000000..6ae8645
--- /dev/null
@@ -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";
+};
index d7aef12..23ba56d 100644 (file)
                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>;
                };
 
                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>;
                };
 
                        compatible = "allwinner,sun6i-a31-wdt";
                        reg = <0x01c20ca0 0x20>;
                        interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                };
 
                lradc: lradc@1c22800 {
index 18156ff..d3b337b 100644 (file)
 &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 {
        status = "okay";
 };
 
+&mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
 &mmc0 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc0_pins>;
index 2ed28d9..bbc6335 100644 (file)
 &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>;
        };
index 0c1eec9..c34d505 100644 (file)
                        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 {
                };
 
                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>;
index 84977d4..eba190b 100644 (file)
                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>;
                };
 
                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>;
                        compatible = "allwinner,sun6i-a31-wdt";
                        reg = <0x01c20ca0 0x20>;
                        interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                };
 
                spdif: spdif@1c21000 {
                        resets = <&ccu RST_BUS_HDMI1>;
                        reset-names = "ctrl";
                        phys = <&hdmi_phy>;
-                       phy-names = "hdmi-phy";
+                       phy-names = "phy";
                        status = "disabled";
 
                        ports {
                };
 
                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>;
index d6a1fc2..dfae90a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ARM Ltd. Versatile Express
  *
index 8e57e15..2e29d77 100644 (file)
                        };
                };
        };
-};
\ No newline at end of file
+};
index 9466913..2873224 100644 (file)
 };
 
 &i2c0 {
-       clock-frequency = <400000>;
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c0>;
        status = "okay";
        };
 };
 
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       watchdog@38 {
+               compatible = "zii,rave-wdt";
+               reg = <0x38>;
+       };
+};
+
 &snvsrtc {
        status = "disabled";
 };
                >;
        };
 
+       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
index d7019e8..dc8a5f3 100644 (file)
                #gpio-cells = <2>;
                reg = <0x20>;
                gpio-controller;
+               interrupt-parent = <&gpio1>;
+               interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
        };
 
        lm75@4e {
                        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
                >;
        };
 
-       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
index 9dde83c..77e1484 100644 (file)
                >;
        };
 
-       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
index e6b98b6..822cddf 100644 (file)
@@ -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
index 7e0486a..dba9355 100644 (file)
@@ -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
index af8b8e1..b0c195e 100644 (file)
@@ -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;
        }
index 09f6fdd..ab25689 100644 (file)
@@ -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:
index d2806bc..07745ee 100644 (file)
@@ -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);
 }
index 05d03f0..71262dc 100644 (file)
@@ -24,6 +24,7 @@
 #define DEEPSLEEP_SLEEPENABLE_BIT      BIT(31)
 
        .text
+       .arch   armv5te
 /*
  * Move DaVinci into deep sleep state
  *
index 1c9a4be..1c05c5b 100644 (file)
@@ -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-netx/Kconfig b/arch/arm/mach-netx/Kconfig
deleted file mode 100644 (file)
index 1e5d9c8..0000000
+++ /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 (file)
index 44ea83f..0000000
+++ /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/Makefile.boot b/arch/arm/mach-netx/Makefile.boot
deleted file mode 100644 (file)
index 2eb23c0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-    zreladdr-y                 += 0x80008000
-
diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c
deleted file mode 100644 (file)
index 2dc80db..0000000
+++ /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 (file)
index 5cdc01f..0000000
+++ /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 (file)
index 88881fd..0000000
+++ /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 (file)
index 223e304..0000000
+++ /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 (file)
index 8425399..0000000
+++ /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 (file)
index 540c921..0000000
+++ /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 (file)
index 7c356a6..0000000
+++ /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 (file)
index de23180..0000000
+++ /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 (file)
index edc1ac9..0000000
+++ /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 (file)
index 465d5e2..0000000
+++ /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 (file)
index ad5e674..0000000
+++ /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 (file)
index 9173815..0000000
+++ /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 (file)
index aa0d5b2..0000000
+++ /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 (file)
index 2e5cc77..0000000
+++ /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 (file)
index d9defa1..0000000
+++ /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 (file)
index 885a618..0000000
+++ /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);
index 5a67a71..76a65df 100644 (file)
@@ -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;
index 820b60a..c54cd7e 100644 (file)
@@ -663,6 +663,11 @@ config ARM_LPAE
        depends on MMU && CPU_32v7 && !CPU_32v6 && !CPU_32v5 && \
                !CPU_32v4 && !CPU_32v3
        select PHYS_ADDR_T_64BIT
+       select SWIOTLB
+       select ARCH_HAS_DMA_COHERENT_TO_PFN
+       select ARCH_HAS_DMA_MMAP_PGPROT
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE
+       select ARCH_HAS_SYNC_DMA_FOR_CPU
        help
          Say Y if you have an ARMv7 processor supporting the LPAE page
          table format and you would like to access memory beyond the
index 8cdb786..04b3643 100644 (file)
@@ -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;
index 4789c60..6774b03 100644 (file)
@@ -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,47 @@ 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)
+{
+       if (!dev_is_dma_coherent(dev))
+               return __get_dma_pgprot(attrs, prot);
+       return 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 */
index 4920a20..16d373d 100644 (file)
@@ -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>
@@ -463,6 +464,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 */
index 79f43ac..08c9941 100644 (file)
@@ -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();
index bb1f1db..61de992 100644 (file)
@@ -52,7 +52,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)
index f6db061..d241802 100644 (file)
@@ -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 (file)
index 0000000..96ab022
--- /dev/null
@@ -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";
+};
index 5ef3c62..04446e4 100644 (file)
        status = "okay";
 };
 
+&r_ir {
+       status = "okay";
+};
+
 &r_rsb {
        status = "okay";
 
index 9cc9bdd..69128a6 100644 (file)
                        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>;
                        resets = <&ccu RST_BUS_HDMI1>;
                        reset-names = "ctrl";
                        phys = <&hdmi_phy>;
-                       phy-names = "hdmi-phy";
+                       phy-names = "phy";
                        status = "disabled";
 
                        ports {
                        #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";
                                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";
                                     "allwinner,sun6i-a31-wdt";
                        reg = <0x01c20ca0 0x20>;
                        interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                };
        };
 };
index 0dc33c9..1d05d57 100644 (file)
@@ -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 {
                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 {
        };
 };
 
+&r_ir {
+       status = "okay";
+};
+
 &r_pio {
        /*
         * PL0 and PL1 are used for PMIC I2C
        vcc-pm-supply = <&reg_aldo1>;
 };
 
+&spdif {
+       status = "okay";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_ph_pins>;
index 17d4969..eb379cd 100644 (file)
                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";
 
                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";
 };
        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 */
        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";
 };
 &pio {
        vcc-pc-supply = <&reg_bldo2>;
        vcc-pd-supply = <&reg_cldo1>;
+       vcc-pg-supply = <&reg_vcc_wifi_io>;
 };
 
 &r_i2c {
index 62e2794..ec9b6a5 100644 (file)
        };
 };
 
+&r_ir {
+       status = "okay";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_ph_pins>;
index 1898345..30102da 100644 (file)
        };
 };
 
+&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 (file)
index 0000000..7e7cb10
--- /dev/null
@@ -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";
+};
index 7628a7c..4020a1a 100644 (file)
                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";
                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 {
                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>;
                        #dma-cells = <1>;
                };
 
-               sid: sid@3006000 {
+               sid: efuse@3006000 {
                        compatible = "allwinner,sun50i-h6-sid";
                        reg = <0x03006000 0x400>;
                };
                                     "allwinner,sun6i-a31-wdt";
                        reg = <0x030090a0 0x20>;
                        interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                        /* Broken on some H6 boards */
                        status = "disabled";
                };
                                     <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>;
                                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";
                                bias-pull-up;
                        };
 
+                       spdif_tx_pin: spdif-tx-pin {
+                               pins = "PH7";
+                               function = "spdif";
+                       };
+
                        uart0_ph_pins: uart0-ph-pins {
                                pins = "PH0", "PH1";
                                function = "uart0";
                        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";
                        };
                };
 
+               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";
                        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";
                        };
                };
 
+               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>;
                                     "allwinner,sun6i-a31-wdt";
                        reg = <0x07020400 0x20>;
                        interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
                };
 
                r_intc: interrupt-controller@7021000 {
                        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>;
                                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>;
index b05d781..144a2c1 100644 (file)
                        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>;
                        #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 {
index 07b861f..edbf128 100644 (file)
@@ -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,4 @@ 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
index 6219337..12bf959 100644 (file)
                                 <&clkc CLKID_FCLK_DIV2>,
                                 <&clkc CLKID_MPLL2>;
                        clock-names = "stmmaceth", "clkin0", "clkin1";
+                       rx-fifo-depth = <4096>;
+                       tx-fifo-depth = <2048>;
                        status = "disabled";
                };
 
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 (file)
index 0000000..cd3d23d
--- /dev/null
@@ -0,0 +1,2420 @@
+// 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-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";
+                                       };
+                               };
+                       };
+
+                       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>;
+                                       };
+                               };
+                       };
+               };
+
+               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_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;
+                                               };
+                                       };
+                               };
+                       };
+
+                       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>;
+                       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>;
+                               };
+                       };
+               };
+
+               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-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>;
+               };
+
+               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>;
+       };
+
+};
index c7a8736..c9fa23a 100644 (file)
                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";
        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>;
        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>;
index 8551fbd..2a324f0 100644 (file)
                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 {
        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>;
        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";
index fe4013c..c1e58a6 100644 (file)
                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";
        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>;
        pinctrl-names = "default";
 };
 
+&pwm_AO_cd {
+       pinctrl-0 = <&pwm_ao_d_e_pins>;
+       pinctrl-names = "default";
+       clocks = <&xtal>;
+       clock-names = "clkin1";
+       status = "okay";
+};
+
 &ext_mdio {
        external_phy: ethernet-phy@0 {
                /* Realtek RTL8211F (0x001cc916) */
index f8d43e3..733a9d4 100644 (file)
@@ -3,56 +3,11 @@
  * 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"
 
 / {
        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>;
                };
        };
 
-       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)>;
-       };
-
-       xtal: xtal-clk {
-               compatible = "fixed-clock";
-               clock-frequency = <24000000>;
-               clock-output-names = "xtal";
-               #clock-cells = <0>;
-       };
-
+&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 (file)
index 0000000..73128ed
--- /dev/null
@@ -0,0 +1,15 @@
+// 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-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 (file)
index 0000000..d61f430
--- /dev/null
@@ -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 (file)
index 0000000..9c3ca2e
--- /dev/null
@@ -0,0 +1,544 @@
+// 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>
+#include <dt-bindings/sound/meson-g12a-tohdmitx.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 */
+       };
+
+       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;
+       };
+
+       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 */
+       };
+
+       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";
+};
+
+&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>;
+};
+
+&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>;
+};
+
+&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>;
+};
+
+&frddr_a {
+       status = "okay";
+};
+
+&frddr_b {
+       status = "okay";
+};
+
+&frddr_c {
+       status = "okay";
+};
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>;
+       pinctrl-names = "default";
+       hdmi-supply = <&vcc_5v>;
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
+
+&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_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";
+};
+
+&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>;
+};
+
+&tdmif_b {
+       status = "okay";
+};
+
+&tdmout_b {
+       status = "okay";
+};
+
+&tohdmitx {
+       status = "okay";
+};
+
+&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";
+};
index 81780ff..6cfc2c6 100644 (file)
@@ -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 {
                /* 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";
        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) */     
        pinctrl-names = "default";
 };
 
+&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 */
 &sd_emmc_b {
        status = "okay";
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 (file)
index 0000000..6bcf972
--- /dev/null
@@ -0,0 +1,15 @@
+// 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-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 (file)
index 0000000..046cc33
--- /dev/null
@@ -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>;
+               };
+       };
+};
index 9e88e51..d5edbc1 100644 (file)
@@ -4,12 +4,15 @@
  * Author: Neil Armstrong <narmstrong@baylibre.com>
  */
 
-#include "meson-g12a.dtsi"
+#include "meson-g12-common.dtsi"
 
 / {
        compatible = "amlogic,g12b";
 
        cpus {
+               #address-cells = <0x2>;
+               #size-cells = <0x0>;
+
                cpu-map {
                        cluster0 {
                                core0 {
                        };
                };
 
-               /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";
                        enable-method = "psci";
                        next-level-cache = <&l2>;
                };
+
+               l2: l2-cache0 {
+                       compatible = "cache";
+               };
        };
 };
 
 &clkc {
        compatible = "amlogic,g12b-clkc";
 };
+
+&sd_emmc_a {
+       amlogic,dram-access-quirk;
+};
index 74d03fc..ca4b834 100644 (file)
                        };
                };
 
+               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: periphs@c8834000 {
                        compatible = "simple-bus";
                        reg = <0x0 0xc8834000 0x0 0x2000>;
                               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";
                };
 
index f734faa..0cb4032 100644 (file)
        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";
+};
index c959456..a09c53a 100644 (file)
        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";
+};
index 7a85a82..a0e677d 100644 (file)
 &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-sm1-sei610.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts
new file mode 100644 (file)
index 0000000..5700cd7
--- /dev/null
@@ -0,0 +1,300 @@
+// 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>;
+               };
+       };
+
+       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;
+       };
+
+       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>;
+};
+
+&ethmac {
+       status = "okay";
+       phy-handle = <&internal_ephy>;
+       phy-mode = "rmii";
+};
+
+&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_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";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
new file mode 100644 (file)
index 0000000..e902d4f
--- /dev/null
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-g12-common.dtsi"
+
+/ {
+       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";
+               };
+       };
+};
+
+&cecb_AO {
+       compatible = "amlogic,meson-sm1-ao-cec";
+};
+
+&clk_msr {
+       compatible = "amlogic,meson-sm1-clk-measure";
+};
+
+&pwrc_vpu {
+       status = "disabled";
+};
+
+&vpu {
+       status = "disabled";
+};
index 6877070..62ab0d5 100644 (file)
                                <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 */
-                               };
-                       };
-               };
        };
 };
index 454cf6c..03a7bf0 100644 (file)
                                        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 {
index c043aca..93fce8f 100644 (file)
@@ -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
index ec6257a..124a7e2 100644 (file)
                        #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";
                };
 
                        #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";
                };
 
index de6ef39..5e14e5a 100644 (file)
        status = "okay";
 };
 
+&esdhc {
+       status = "okay";
+};
+
+&esdhc1 {
+       status = "okay";
+};
+
 &i2c0 {
        status = "okay";
 
index 9fb9113..1a69221 100644 (file)
        };
 };
 
+&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";
 
index 7975519..b139b29 100644 (file)
@@ -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 {
                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 {
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                };
 
                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 {
                        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>;
                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 (file)
index 0000000..3595be0
--- /dev/null
@@ -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>;
+               };
+       };
+};
index 6f48d21..120e62d 100644 (file)
        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";
 
index dacd8cf..d1469b0 100644 (file)
                        #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>;
                };
 
                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;
                };
 
                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;
                };
 
                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;
                };
 
                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;
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                        #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";
                };
 
                                     <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>;
index 3ace919..64101c9 100644 (file)
                        };
                };
 
+               console@8340020 {
+                       compatible = "fsl,dpaa2-console";
+                       reg = <0x00000000 0x08340020 0 0x2>;
+               };
+
                ptp-timer@8b95000 {
                        compatible = "fsl,dpaa2-ptp";
                        reg = <0x0 0x8b95000 0x0 0x100>;
index e6fdba3..408e0ec 100644 (file)
                        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";
                };
                        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";
                };
 
                        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";
                };
 
                        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";
                };
 
                        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";
                };
                        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";
                };
 
                        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";
                };
 
                        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";
                };
 
                        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>;
index ee7f2b2..f7a15f3 100644 (file)
@@ -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;
                };
        };
 };
        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>;
        };
 };
 
+&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";
 
                >;
        };
 
+       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
                >;
        };
 
+       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
index e25f7fc..cffa899 100644 (file)
 #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
 #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
index 232a741..984ea7b 100644 (file)
                #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 {
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
                        operating-points-v2 = <&a53_opp_table>;
+                       cpu-idle-states = <&cpu_pd_wait>;
                };
 
                A53_L2: l2-cache0 {
                        opp-microvolt = <850000>;
                        opp-supported-hw = <0xe>, <0x7>;
                        clock-latency-ns = <150000>;
+                       opp-suspend;
                };
 
                opp-1600000000 {
                        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;
                };
        };
 
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 10 30>;
                        };
 
                        gpio2: gpio@30210000 {
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 40 21>;
                        };
 
                        gpio3: gpio@30220000 {
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 61 26>;
                        };
 
                        gpio4: gpio@30230000 {
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 87 32>;
                        };
 
                        gpio5: gpio@30240000 {
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 119 30>;
                        };
 
                        wdog1: watchdog@30280000 {
                                         <&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>;
                                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";
                                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";
                        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 (file)
index 0000000..11c705d
--- /dev/null
@@ -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 (file)
index 0000000..785f4c4
--- /dev/null
@@ -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";
+       };
+};
index e3df9b8..0595812 100644 (file)
 &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 (file)
index 0000000..f52e872
--- /dev/null
@@ -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
+               >;
+       };
+};
index 5179e22..683a110 100644 (file)
        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 (file)
index 0000000..c832bf0
--- /dev/null
@@ -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 (file)
index 0000000..8a4aee2
--- /dev/null
@@ -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 (file)
index 0000000..d7f03c6
--- /dev/null
@@ -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
+               >;
+       };
+};
index 7a1706f..af99473 100644 (file)
                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>;
                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>;
        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 {
 };
 
 &usb3_phy0 {
-       vbus-supply = <&reg_5p0_user_usb>;
+       vbus-supply = <&ucs1002>;
        status = "okay";
 };
 
                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
                >;
        };
                >;
        };
 
-       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
                >;
        };
 
+       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
index d09b808..046a0c8 100644 (file)
                        /* Industrial only */
                        opp-supported-hw = <0xf>, <0x4>;
                        clock-latency-ns = <150000>;
+                       opp-suspend;
                };
 
                opp-1000000000 {
                        /* 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;
                };
        };
 
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 10 30>;
                        };
 
                        gpio2: gpio@30210000 {
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 40 21>;
                        };
 
                        gpio3: gpio@30220000 {
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 61 26>;
                        };
 
                        gpio4: gpio@30230000 {
                                #gpio-cells = <2>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 87 32>;
                        };
 
                        gpio5: gpio@30240000 {
                                #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
                        };
 
                        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 {
 
                        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>,
                                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>;
                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>;
                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>;
                        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 (file)
index 0000000..91eef97
--- /dev/null
@@ -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
+               >;
+       };
+};
index bfdada2..1946805 100644 (file)
                >;
        };
 };
+
+&adma_dsp {
+       status = "okay";
+};
index 05fa0b7..1133b41 100644 (file)
@@ -30,6 +30,9 @@
                mmc2 = &usdhc3;
                mu1 = &lsio_mu1;
                serial0 = &adma_lpuart0;
+               serial1 = &adma_lpuart1;
+               serial2 = &adma_lpuart2;
+               serial3 = &adma_lpuart3;
        };
 
        cpus {
                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>;
                        #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";
                };
                        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";
                };
                        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";
                };
                        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";
                };
index e4ceb3a..36abc25 100644 (file)
                        #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 {
index d8e555c..1fb195c 100644 (file)
        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>,
index c2749c4..97f84aa 100644 (file)
        #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>;
                        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";
                        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>;
                        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>;
                        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>;
                        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>;
                        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>;
index 3311a98..e1b95c3 100644 (file)
@@ -10,6 +10,7 @@
 / {
        aliases {
                serial0 = &scif2;
+               serial1 = &hscif0;
        };
 
        chosen {
        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>;
                };
                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 {
                regulator-always-on;
        };
 
+       sound_card: sound {
+               compatible = "audio-graph-card";
+
+               label = "rcar-sound";
+
+               dais = <&rsnd_port0>;
+       };
+
        vbus0_usb2: regulator-vbus0-usb2 {
                compatible = "regulator-fixed";
 
                          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>;
        };
 };
 
+&audio_clk_a {
+       clock-frequency = <22579200>;
+};
+
 &du {
        clocks = <&cpg CPG_MOD 724>,
                 <&cpg CPG_MOD 723>,
                                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>;
        };
 };
 
        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>;
        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";
                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";
        };
 };
 
+&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";
        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>;
index 07a6eea..4280b19 100644 (file)
        };
 };
 
+&can0 {
+       pinctrl-0 = <&can0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&can1 {
+       pinctrl-0 = <&can1_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
 &pciec0 {
        status = "okay";
 };
                        drive-strength = <12>;
                };
        };
+
+       can0_pins: can0 {
+               groups = "can0_data_a";
+               function = "can0";
+       };
+
+       can1_pins: can1 {
+               groups = "can1_data";
+               function = "can1";
+       };
 };
index f209457..06c7c84 100644 (file)
                                 <&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";
                                 <&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>;
                                <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>,
                                      "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>;
                                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>;
                        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";
                                };
                        };
                };
                        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>;
                                        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>;
-                               };
-                       };
                };
        };
 
index 46a77ee..c99b1de 100644 (file)
                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";
 
                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 {
                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";
                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";
index e7b5bf2..a1c2de9 100644 (file)
                                 <&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";
                                 <&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";
                                      "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>;
                                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>;
                        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 {
                        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 {
                        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>;
                        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>;
 
                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 {
                        resets = <&cpg 727>;
                        status = "disabled";
 
+                       renesas,companion = <&lvds1>;
+
                        ports {
                                #address-cells = <1>;
                                #size-cells = <0>;
                        polling-delay = <1000>;
                        thermal-sensors = <&thermal>;
 
+                       cooling-maps {
+                       };
+
                        trips {
                                cpu-crit {
                                        temperature = <120000>;
                                        type = "critical";
                                };
                        };
-
-                       cooling-maps {
-                       };
                };
        };
 
index c1a56ea..c729686 100644 (file)
        status = "okay";
 };
 
-&sound_card {
-       dais = <&rsnd_port0     /* ak4613 */
-               &rsnd_port1     /* HDMI0  */
-               &rsnd_port2>;   /* HDMI1  */
-};
-
 &hdmi0 {
        status = "okay";
 
        status = "okay";
 };
 
+&pfc {
+       usb2_pins: usb2 {
+               groups = "usb2";
+               function = "usb2";
+       };
+};
+
 &rcar_sound {
        ports {
                /* rsnd_port0 is on salvator-common */
        };
 };
 
-&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";
index 40d10da..e4650ae 100644 (file)
@@ -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";
                #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";
                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 {
                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 {
        };
 };
 
-&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 {
index d2d48b3..72874f6 100644 (file)
        status = "okay";
 };
 
-&sound_card {
-       dais = <&rsnd_port0     /* ak4613 */
-               &rsnd_port1     /* HDMI0  */
-               &rsnd_port2>;   /* HDMI1  */
-};
-
 &hdmi0 {
        status = "okay";
 
        status = "okay";
 };
 
+&pfc {
+       usb2_pins: usb2 {
+               groups = "usb2";
+               function = "usb2";
+       };
+};
+
 &rcar_sound {
        ports {
                /* rsnd_port0 is on salvator-common */
        };
 };
 
-&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";
index 42101fc..36667c8 100644 (file)
        status = "okay";
 };
 
-&hsusb3 {
-       dr_mode = "otg";
-       status = "okay";
-};
-
-&sound_card {
-       dais = <&rsnd_port0     /* ak4613 */
-               &rsnd_port1     /* HDMI0  */
-               &rsnd_port2>;   /* HDMI1  */
-};
-
 &hdmi0 {
        status = "okay";
 
        remote-endpoint = <&rcar_dw_hdmi1_out>;
 };
 
+&hsusb3 {
+       dr_mode = "otg";
+       status = "okay";
+};
+
 &ohci2 {
        status = "okay";
 };
        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;
        };
 };
 
+&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";
index 1745ac4..95deff6 100644 (file)
                        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>;
                        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>;
                                 <&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 {
index 2aefa53..de37e91 100644 (file)
                      "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  */
+};
index d58ede1..a1cbfef 100644 (file)
                      "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  */
+};
index 26df5b8..3dc9d73 100644 (file)
                                      "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>;
                                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>;
                                };
                        };
 
+                       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>;
                                        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 {
                        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>;
                                        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>;
-                               };
-                       };
                };
        };
 
index 340a3c7..660a024 100644 (file)
                                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  */
+};
index f03a5e9..5cef646 100644 (file)
                                remote-endpoint = <&hdmi0_con>;
                        };
                };
+               port@2 {
+                       reg = <2>;
+                       dw_hdmi0_snd_in: endpoint {
+                               remote-endpoint = <&rsnd_endpoint1>;
+                       };
+               };
        };
 };
 
        };
 };
 
+&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  */
+};
index 131f895..4ae1632 100644 (file)
                        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>;
                        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>;
                        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>;
                        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>;
                        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>;
                        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>;
index 233f26f..2afb91e 100644 (file)
                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 {
                };
        };
 
-       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";
 
                        };
                };
        };
+
+       memory@48000000 {
+               device_type = "memory";
+               /* first 128MB is reserved for secure area. */
+               reg = <0x0 0x48000000 0x0 0x38000000>;
+       };
 };
 
 &avb {
        };
 };
 
+&du {
+       status = "okay";
+};
+
 &extal_clk {
        clock-frequency = <16666666>;
 };
        };
 };
 
+&lvds0 {
+       status = "okay";
+
+       ports {
+               port@1 {
+                       lvds0_out: endpoint {
+                               remote-endpoint = <&thc63lvd1024_in>;
+                       };
+               };
+       };
+};
+
 &pfc {
        avb_pins: avb0 {
                groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk";
 
        status = "okay";
 };
-
-&du {
-       status = "okay";
-};
-
-&lvds0 {
-       status = "okay";
-
-       ports {
-               port@1 {
-                       lvds0_out: endpoint {
-                               remote-endpoint = <&thc63lvd1024_in>;
-                       };
-               };
-       };
-};
index 15cc9fe..d7c7b91 100644 (file)
                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. */
                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 {
        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";
        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";
index 5b6164d..0cd3b37 100644 (file)
                        polling-delay = <1000>;
                        thermal-sensors = <&thermal>;
 
+                       cooling-maps {
+                       };
+
                        trips {
                                cpu-crit {
                                        temperature = <120000>;
                                        type = "critical";
                                };
                        };
-
-                       cooling-maps {
-                       };
                };
        };
 
index 5a7012b..3dde028 100644 (file)
                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;
        };
                };
        };
 
+       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>;
index dd14a41..adbfd8f 100644 (file)
                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";
                };
        };
 
+       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>;
index a901a34..461a47e 100644 (file)
                        #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>;
index 83fc13a..b38f9d4 100644 (file)
                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>
                };
        };
 
-       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 {
                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 {
                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 {
                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 {
                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>;
        };
 };
 
                function = "pwm5";
        };
 
+       scif2_pins: scif2 {
+               groups = "scif2_data_a";
+               function = "scif2";
+       };
+
        sdhi0_pins: sd0 {
                groups = "sdhi0_data4", "sdhi0_ctrl";
                function = "sdhi0";
                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 {
        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>;
        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";
+};
index b431866..455954c 100644 (file)
                                      "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>;
                                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>;
                        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 {
                        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";
                                };
                        };
                };
index 0711170..0bbd4d7 100644 (file)
                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>;
                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";
 
                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>;
        };
 };
 
index 0a344eb..183fef8 100644 (file)
                        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>;
                        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";
 
                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 {
                        polling-delay = <1000>;
                        thermal-sensors = <&thermal>;
 
+                       cooling-maps {
+                       };
+
                        trips {
                                cpu-crit {
                                        temperature = <120000>;
                                        type = "critical";
                                };
                        };
-
-                       cooling-maps {
-                       };
                };
        };
 
index 5c2c847..21e0105 100644 (file)
                };
        };
 
+       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";
 
                          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";
 
                #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
                        };
                };
        };
+
+       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 {
index 27851a7..2021777 100644 (file)
 };
 
 &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";
                        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>;
                        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>;
                        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 {
                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>;
                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 {
                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>;
+                       };
+               };
        };
 };
 
        };
 };
 
-&usb2_phy0 {
-       pinctrl-0 = <&usb0_pins>;
-       pinctrl-names = "default";
-
-       status = "okay";
-};
-
-&xhci0 {
-       status = "okay";
-};
-
 &sound_card {
        dais = <&rsnd_port0     /* ak4613 */
                &rsnd_port1     /* HDMI0  */
                >;
 };
 
-&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";
 };
index 7e498b4..3ef8917 100644 (file)
        };
 };
 
+&rwdt {
+       timeout-sec = <60>;
+       status = "okay";
+};
+
 &scif2 {
        pinctrl-0 = <&scif2_pins>;
        pinctrl-names = "default";
 
        status = "okay";
 };
-
-&rwdt {
-       timeout-sec = <60>;
-       status = "okay";
-};
index daa2c78..1f18a93 100644 (file)
@@ -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
index 3e2272b..e152b0c 100644 (file)
                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 (file)
index 0000000..73be38a
--- /dev/null
@@ -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";
+};
index eb55940..0401d4e 100644 (file)
                };
        };
 
+       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>;
        status = "okay";
 };
 
+&pwm1 {
+       status = "okay";
+};
+
 &pwm2 {
        status = "okay";
 };
        status = "okay";
 };
 
+&spi1 {
+       status = "okay";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <10000000>;
+       };
+};
+
 &tcphy0 {
        status = "okay";
 };
index 79155a8..89e4c8b 100644 (file)
@@ -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);
 }
 
index 407e2bf..c96ffa4 100644 (file)
  */
 
 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 */
index 987926e..063c964 100644 (file)
@@ -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)
index 8e79ce9..76a1447 100644 (file)
@@ -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")));
index 3c7037c..b618017 100644 (file)
@@ -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 {                                                                   \
        /*                                                              \
index a8b205e..ddf9d76 100644 (file)
 
 #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), \
index b7ba758..fb04f10 100644 (file)
@@ -210,7 +210,11 @@ extern u64                 vabits_user;
 #define __tag_reset(addr)      untagged_addr(addr)
 #define __tag_get(addr)                (__u8)((u64)(addr) >> 56)
 #else
-#define __tag_set(addr, tag)   (addr)
+static inline const void *__tag_set(const void *addr, u8 tag)
+{
+       return addr;
+}
+
 #define __tag_reset(addr)      (addr)
 #define __tag_get(addr)                0
 #endif
@@ -301,8 +305,8 @@ static inline void *phys_to_virt(phys_addr_t x)
 #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));               \
+       const void *__addr_tag =                                        \
+               __tag_set((void *)__addr, page_kasan_tag(page));        \
        ((void *)__addr_tag);                                           \
 })
 
index 87a4b2d..e09760e 100644 (file)
@@ -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)
@@ -301,7 +301,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 +396,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 +450,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)
index fd5b1a4..844e296 100644 (file)
@@ -193,6 +193,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 +210,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 +229,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;
 }
index b1dd039..1dcf63a 100644 (file)
@@ -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)
 
index df45af9..4d9b1f4 100644 (file)
@@ -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 */
index f481277..c50ee1b 100644 (file)
@@ -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)
@@ -51,6 +53,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
        return ret;
 }
 
+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)
 {
@@ -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;
index b551b74..5e1e648 100644 (file)
@@ -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__
 
index f29f36a..d19d14b 100644 (file)
@@ -225,8 +225,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 +468,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;
index f8719bd..48222a4 100644 (file)
@@ -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;
 }
index 9cdc459..320a30d 100644 (file)
@@ -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
@@ -858,11 +858,15 @@ el0_fpsimd_exc:
        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
        enable_da_f
 #ifdef CONFIG_TRACE_IRQFLAGS
index eec4776..37d3912 100644 (file)
@@ -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,
index dceb845..38ee151 100644 (file)
@@ -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;
                }
index 46e643e..03ff15b 100644 (file)
@@ -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)
index 9d63514..b0e03e0 100644 (file)
@@ -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);
 }
 
index bd5dfff..c445282 100644 (file)
@@ -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>
@@ -167,33 +168,6 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
        __this_cpu_write(current_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.
@@ -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);
index 6a869d9..f674f28 100644 (file)
@@ -398,7 +398,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;
@@ -442,6 +442,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 +497,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 +525,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;
index b21cba9..a5e8b3b 100644 (file)
@@ -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);
index ea90d3b..018a33e 100644 (file)
@@ -152,8 +152,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
                                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)
index 62d3951..a336cb1 100644 (file)
@@ -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>
  *     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);
 
index 9f25aed..0b29464 100644 (file)
@@ -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)
index 8c03456..32893b3 100644 (file)
@@ -100,18 +100,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 {
@@ -734,6 +733,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)",
index 4ab8630..dd2514b 100644 (file)
@@ -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 $@
index 60a4c62..1fba077 100644 (file)
@@ -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   $@
index 26781da..0fc9872 100644 (file)
 #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);                    \
        }
 
index 0d60e4f..a900181 100644 (file)
@@ -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;
        }
 }
index f26e181..2071260 100644 (file)
@@ -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;
        }
index 9568c11..cfd65b6 100644 (file)
@@ -777,6 +777,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 +864,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 +874,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);
index b079ec7..d150cd6 100644 (file)
@@ -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
index ddf2f39..ed7fad1 100644 (file)
@@ -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
index ee323d8..49d4e14 100644 (file)
@@ -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
index 4e248d5..66b2268 100644 (file)
@@ -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
index e81e7ff..670c020 100644 (file)
@@ -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
index ec60e49..211c983 100644 (file)
@@ -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
index 1f730de..cc88a08 100644 (file)
@@ -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)
index e0dd668..f777e44 100644 (file)
@@ -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;
 }
 
index 5f209f1..df7ddd2 100644 (file)
@@ -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();
index e5de6ba..754094b 100644 (file)
@@ -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;
index 2cfe839..1109924 100644 (file)
@@ -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;
index 7c04b17..96c13a0 100644 (file)
@@ -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);
index d02eb9d..925c723 100644 (file)
@@ -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;
        }
index 14b1931..b65b169 100644 (file)
@@ -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__
index b5d58ea..bc0b92a 100644 (file)
@@ -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
index 511e653..c264ef1 100644 (file)
@@ -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__
index 7379366..31b9b43 100644 (file)
@@ -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
index d54a5d6..f17396d 100644 (file)
@@ -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
index 2977534..48d0032 100644 (file)
@@ -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
index 1a6e01c..d76217c 100644 (file)
@@ -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
index dc89af7..6c1e664 100644 (file)
@@ -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
index a0b2f7b..410795e 100644 (file)
@@ -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
index 8acb8fa..3b77d72 100644 (file)
@@ -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
index 2da8624..1e5879c 100644 (file)
@@ -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
index bfd7872..2ac3a64 100644 (file)
@@ -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/default_defconfig
deleted file mode 100644 (file)
index 5b877ca..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PA7100LC=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_IOMMU_CCIO=y
-CONFIG_GSC_LASI=y
-CONFIG_GSC_WAX=y
-CONFIG_EISA=y
-CONFIG_PCI=y
-CONFIG_GSC_DINO=y
-CONFIG_PCI_LBA=y
-CONFIG_PCCARD=y
-CONFIG_YENTA=y
-CONFIG_PD6729=y
-CONFIG_I82092=y
-CONFIG_BINFMT_MISC=m
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_DIAG=m
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-CONFIG_LLC2=m
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_PCMCIA=m
-CONFIG_PARPORT_1284=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_NS87415=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_LASI700=y
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_ZALON=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-CONFIG_MD_RAID10=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
-CONFIG_DUMMY=m
-CONFIG_TUN=m
-CONFIG_ACENIC=y
-CONFIG_TIGON3=y
-CONFIG_NET_TULIP=y
-CONFIG_TULIP=y
-CONFIG_LASI_82596=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-# CONFIG_KEYBOARD_HIL_OLD is not set
-CONFIG_MOUSE_SERIAL=y
-CONFIG_LEGACY_PTY_COUNT=64
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_CS=y
-CONFIG_SERIAL_8250_NR_UARTS=17
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_PRINTER=m
-CONFIG_PPDEV=m
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_DUMMY_CONSOLE_COLUMNS=128
-CONFIG_DUMMY_CONSOLE_ROWS=48
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_DYNAMIC_MINORS=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_AD1889=y
-CONFIG_SND_HARMONY=y
-CONFIG_HID_GYRATION=y
-CONFIG_HID_NTRIG=y
-CONFIG_HID_PANTHERLORD=y
-CONFIG_HID_PETALYNX=y
-CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SUNPLUS=y
-CONFIG_HID_TOPSEED=y
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V4=y
-CONFIG_CIFS=m
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=y
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_FS=y
-CONFIG_HEADERS_INSTALL=y
-CONFIG_HEADERS_CHECK=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_KEYS=y
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-# CONFIG_CRYPTO_HW is not set
-CONFIG_LIBCRC32C=m
-CONFIG_FONTS=y
diff --git a/arch/parisc/configs/defconfig b/arch/parisc/configs/defconfig
new file mode 100644 (file)
index 0000000..5b877ca
--- /dev/null
@@ -0,0 +1,206 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PA7100LC=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_PCI=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_PCCARD=y
+CONFIG_YENTA=y
+CONFIG_PD6729=y
+CONFIG_I82092=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_DIAG=m
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_LLC2=m
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_1284=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_LASI700=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_TUN=m
+CONFIG_ACENIC=y
+CONFIG_TIGON3=y
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+CONFIG_LASI_82596=y
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+# CONFIG_KEYBOARD_HIL_OLD is not set
+CONFIG_MOUSE_SERIAL=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=17
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_PRINTER=m
+CONFIG_PPDEV=m
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_AD1889=y
+CONFIG_SND_HARMONY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V4=y
+CONFIG_CIFS=m
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_INSTALL=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+# CONFIG_CRYPTO_HW is not set
+CONFIG_LIBCRC32C=m
+CONFIG_FONTS=y
index e09cf2d..904034d 100644 (file)
@@ -50,6 +50,10 @@ struct kprobe_ctlblk {
 
 int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs);
 int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs);
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+       return 0;
+}
 
 #endif /* CONFIG_KPROBES */
 #endif /* _PARISC_KPROBES_H */
index d784ccd..b6fb30f 100644 (file)
@@ -181,8 +181,9 @@ 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
index ba67893..df46b0e 100644 (file)
@@ -63,7 +63,7 @@ ENTRY_CFI(flush_tlb_all_local)
 
        /* Flush Instruction Tlb */
 
-       LDREG           ITLB_SID_BASE(%r1), %r20
+88:    LDREG           ITLB_SID_BASE(%r1), %r20
        LDREG           ITLB_SID_STRIDE(%r1), %r21
        LDREG           ITLB_SID_COUNT(%r1), %r22
        LDREG           ITLB_OFF_BASE(%r1), %arg0
@@ -103,6 +103,7 @@ fitonemiddle:                                       /* Loop if LOOP = 1 */
        add             %r21, %r20, %r20                /* increment space */
 
 fitdone:
+       ALTERNATIVE(88b, fitdone, ALT_COND_NO_SPLIT_TLB, INSN_NOP)
 
        /* Flush Data Tlb */
 
index b6c4b25..3747a0c 100644 (file)
@@ -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
index 6dd4669..adbd5e2 100644 (file)
@@ -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)) {
index d8dcd88..77f6ebf 100644 (file)
@@ -121,6 +121,7 @@ config PPC
        select ARCH_32BIT_OFF_T if PPC32
        select ARCH_HAS_DEBUG_VIRTUAL
        select ARCH_HAS_DEVMEM_IS_ALLOWED
+       select ARCH_HAS_DMA_MMAP_PGPROT
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_GCOV_PROFILE_ALL
index b3388d9..45e3137 100644 (file)
@@ -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__ */
index 463c63a..1111202 100644 (file)
 #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
index dc9a1ca..c6bbe97 100644 (file)
@@ -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
 }
 
index 68473c3..b0720c7 100644 (file)
@@ -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_ */
index b551b74..5e1e648 100644 (file)
@@ -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__
 
index 01555c6..be48c22 100644 (file)
@@ -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;
index 56dfa7a..ea0c692 100644 (file)
@@ -49,7 +49,8 @@ obj-y                         := cputable.o ptrace.o syscalls.o \
                                   signal.o sysfs.o cacheinfo.o time.o \
                                   prom.o traps.o setup-common.o \
                                   udbg.o misc.o io.o misc_$(BITS).o \
-                                  of_platform.o prom_parse.o
+                                  of_platform.o prom_parse.o \
+                                  dma-common.o
 obj-$(CONFIG_PPC64)            += setup_64.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
                                   paca.o nvram_64.o firmware.o
index 7107ad8..92045ed 100644 (file)
@@ -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/dma-common.c b/arch/powerpc/kernel/dma-common.c
new file mode 100644 (file)
index 0000000..dc7ef6b
--- /dev/null
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Contains common dma routines for all powerpc platforms.
+ *
+ * Copyright (C) 2019 Shawn Anastasio.
+ */
+
+#include <linux/mm.h>
+#include <linux/dma-noncoherent.h>
+
+pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot,
+               unsigned long attrs)
+{
+       if (!dev_is_dma_coherent(dev))
+               return pgprot_noncached(prot);
+       return prot;
+}
index 85fdb6d..54fab22 100644 (file)
@@ -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)
index d9105fc..0a0b531 100644 (file)
@@ -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
index eee5bef..6ba3cc2 100644 (file)
@@ -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
index f50b708..98600b2 100644 (file)
@@ -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.
                         */
index 2f80e27..1175155 100644 (file)
@@ -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,
index 3331749..43f736e 100644 (file)
 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
index 6539361..18f244a 100644 (file)
@@ -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:
index ec1804f..cde3f5a 100644 (file)
@@ -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);
 
index 6ca0d73..e3ba670 100644 (file)
@@ -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;
 }
index 5596c8e..a998823 100644 (file)
@@ -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;
 }
 
 /*
index 0dba7eb..3e566c2 100644 (file)
@@ -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;
index 9a5963e..b8ad14b 100644 (file)
@@ -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);
index 0d62be3..74f4555 100644 (file)
@@ -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;
index 9259337..9191a66 100644 (file)
@@ -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
index c8ec670..a5ac371 100644 (file)
@@ -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;
 
index 082c7e1..1cdb395 100644 (file)
@@ -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;
 }
 
index 4098349..42b5ec2 100644 (file)
@@ -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";
                        #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";
+               };
+
        };
 };
index 0b55c53..93d68cb 100644 (file)
                disable-wp;
        };
 };
+
+&eth0 {
+       status = "okay";
+       phy-mode = "gmii";
+       phy-handle = <&phy0>;
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+};
index b7b749b..93205c0 100644 (file)
@@ -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_SPI=y
+CONFIG_SPI_SIFIVE=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
@@ -66,8 +69,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 +87,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
index 1efaedd..16970f2 100644 (file)
@@ -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
index 6271665..d86cb17 100644 (file)
@@ -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
index 0b9b58b..7d0b32e 100644 (file)
@@ -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
index 1920deb..f671e16 100644 (file)
@@ -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
index 7d78614..4e76460 100644 (file)
@@ -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
  *
index 92d8f7c..882547f 100644 (file)
@@ -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
  */
index 053f809..84f2dfc 100644 (file)
@@ -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
  */
index b58e00c..411dd7b 100644 (file)
@@ -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.
index 0e2eeeb..13ce76c 100644 (file)
@@ -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>
index f1d6ffe..49a5852 100644 (file)
@@ -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)
 
index 8e364eb..267feaa 100644 (file)
@@ -5,5 +5,3 @@ lib-y   += memset.o
 lib-y  += uaccess.o
 
 lib-$(CONFIG_64BIT) += tishift.o
-
-lib-$(CONFIG_32BIT) += udivdi3.o
index 87ff89e..f51c9a0 100644 (file)
@@ -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/udivdi3.S b/arch/riscv/lib/udivdi3.S
deleted file mode 100644 (file)
index 3f07476..0000000
+++ /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)
index 7cba96e..4cf0bdd 100644 (file)
@@ -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
index ad57c22..1c3b2b2 100644 (file)
@@ -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);
 
index 028aab0..2087bed 100644 (file)
@@ -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"
index 3c49bde..b8aa6a9 100644 (file)
@@ -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;
index 3bdd813..c34a638 100644 (file)
@@ -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 (file)
index 0000000..d32e58b
--- /dev/null
@@ -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;
index e26d441..74e78ec 100644 (file)
@@ -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
index e4bc400..68d3ca8 100644 (file)
@@ -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
index d92bab8..be09a20 100644 (file)
@@ -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
index 42f2375..e1fcc03 100644 (file)
@@ -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;
        }
index 9900d65..b8833ac 100644 (file)
@@ -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);
 }
index a4d3809..823578c 100644 (file)
@@ -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>
 
index db5ef22..f647d56 100644 (file)
@@ -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
index 82deb8f..70bd657 100644 (file)
@@ -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)
index b675568..9e9f75e 100644 (file)
@@ -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_ */
index cefe7c7..3ed42ff 100644 (file)
@@ -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__
 
index fd32b1c..451ba7d 100644 (file)
@@ -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
 
index 494c34c..8c5755f 100644 (file)
@@ -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));
 
 /**
index ac06c39..34bdc60 100644 (file)
@@ -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:
index 5aea1a5..f384a18 100644 (file)
@@ -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
index 2c0a515..6837aff 100644 (file)
@@ -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;
index 1dded39..3b664cb 100644 (file)
@@ -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)
index d4e031f..5f1fd15 100644 (file)
@@ -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.
index 2b94b0a..2531779 100644 (file)
@@ -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;
index a90d3e9..3054e9c 100644 (file)
 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
index 243d8b1..c6bc190 100644 (file)
@@ -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
index 49d5532..7e0eb40 100644 (file)
@@ -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
index 3f520cd..f329dcb 100644 (file)
@@ -2516,16 +2516,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");
index 9658059..29d9470 100644 (file)
@@ -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)
 {
index 3b93ba0..5d67b81 100644 (file)
@@ -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
index 6350766..7b0bb47 100644 (file)
@@ -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;
index 1e668b9..39c3a6e 100644 (file)
@@ -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;
index 99e0621..54fcdf6 100644 (file)
@@ -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,
        },
        { }
 };
index 884a9ca..f4f4c2c 100644 (file)
@@ -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 $@;
index 1170dd2..4bd19f8 100644 (file)
@@ -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>
index f83795f..68100e1 100644 (file)
@@ -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>
index 64c67f2..0dace69 100644 (file)
@@ -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.
  */
index 401e30c..8272a44 100644 (file)
@@ -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;
index 830bd98..515c0ce 100644 (file)
@@ -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
index 2bb986f..4f86928 100644 (file)
@@ -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
 
index 3f5a978..be9ca19 100644 (file)
@@ -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
 
@@ -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
index 9e911a9..648260b 100644 (file)
@@ -20,7 +20,6 @@
 #include <asm/intel-family.h>
 #include <asm/apic.h>
 #include <asm/cpu_device_id.h>
-#include <asm/hypervisor.h>
 
 #include "../perf_event.h"
 
@@ -263,8 +262,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
@@ -4053,7 +4052,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;
 
        /*
@@ -4955,6 +4954,7 @@ __init int intel_pmu_init(void)
 
        case INTEL_FAM6_SKYLAKE_X:
                pmem = true;
+               /* fall through */
        case INTEL_FAM6_SKYLAKE_MOBILE:
        case INTEL_FAM6_SKYLAKE_DESKTOP:
        case INTEL_FAM6_KABYLAKE_MOBILE:
@@ -5004,6 +5004,7 @@ __init int intel_pmu_init(void)
        case INTEL_FAM6_ICELAKE_X:
        case INTEL_FAM6_ICELAKE_XEON_D:
                pmem = true;
+               /* fall through */
        case INTEL_FAM6_ICELAKE_MOBILE:
        case INTEL_FAM6_ICELAKE_DESKTOP:
                x86_pmu.late_ack = true;
index 2c8db2c..f1269e8 100644 (file)
@@ -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 */
index 998c2cc..e880f24 100644 (file)
 #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 */
 #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 */
index 8282b8d..74e88e5 100644 (file)
@@ -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
@@ -607,15 +609,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;
@@ -1174,6 +1177,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);
index ae91429..ba71a63 100644 (file)
@@ -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)
 {
@@ -113,6 +115,23 @@ long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
        return ret;
 }
 
+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
index 484e3cf..149143c 100644 (file)
@@ -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
 
index 6ebaae9..8b2effe 100644 (file)
@@ -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
 
index 6b18e88..7114801 100644 (file)
@@ -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
 
index df55e1d..9d5c11a 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 #ifndef _ASM_X86_TYPES_H
 #define _ASM_X86_TYPES_H
 
index 66ca906..c6fa3ef 100644 (file)
@@ -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();
@@ -273,6 +268,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
 
@@ -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],
index 1147217..f125bf7 100644 (file)
@@ -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,38 @@ 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_X,         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_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_X,           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 +1117,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;
 
index 4296c70..7218280 100644 (file)
@@ -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:
index a6342c8..f3d3e96 100644 (file)
@@ -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
index c43e96a..c6f791b 100644 (file)
@@ -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) {
index b7f34fe..4ab377c 100644 (file)
@@ -308,9 +308,6 @@ 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));
 
@@ -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;
index 0fdbe89..3c5bbe8 100644 (file)
@@ -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;
index 4f36d32..2d6898c 100644 (file)
@@ -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;
index 8eb67a6..653b7f6 100644 (file)
@@ -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;
+       }
 }
index 329361b..018aebc 100644 (file)
@@ -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;
 }
index 0aa1586..685d17c 100644 (file)
@@ -1548,7 +1548,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 +1565,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)
index 8f72526..24843cf 100644 (file)
@@ -3466,7 +3466,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,
index 19f69df..d685491 100644 (file)
@@ -2143,12 +2143,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 +2219,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 +2251,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 +5190,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;
@@ -7303,6 +7319,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,
 
index 0f13787..ced9fba 100644 (file)
@@ -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);
index a279447..42ed3fa 100644 (file)
@@ -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,
index 58305cf..93b0bd4 100644 (file)
@@ -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);
@@ -7202,7 +7206,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 +7246,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 +7995,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 +8274,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 +8291,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 +9698,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;
index 04967cd..7ad6891 100644 (file)
@@ -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)
 {
index 6c46095..9ceacd1 100644 (file)
@@ -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);
        }
index 3cf302b..8901a1f 100644 (file)
@@ -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)
 
@@ -17,11 +20,34 @@ KCOV_INSTRUMENT := n
 
 # 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.
-
-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)
+# sure how to relocate those.
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_sha256.o         += $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_purgatory.o      += $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_string.o         += $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_kexec-purgatory.o        += $(CC_FLAGS_FTRACE)
+endif
+
+ifdef CONFIG_STACKPROTECTOR
+CFLAGS_REMOVE_sha256.o         += -fstack-protector
+CFLAGS_REMOVE_purgatory.o      += -fstack-protector
+CFLAGS_REMOVE_string.o         += -fstack-protector
+CFLAGS_REMOVE_kexec-purgatory.o        += -fstack-protector
+endif
+
+ifdef CONFIG_STACKPROTECTOR_STRONG
+CFLAGS_REMOVE_sha256.o         += -fstack-protector-strong
+CFLAGS_REMOVE_purgatory.o      += -fstack-protector-strong
+CFLAGS_REMOVE_string.o         += -fstack-protector-strong
+CFLAGS_REMOVE_kexec-purgatory.o        += -fstack-protector-strong
+endif
+
+ifdef CONFIG_RETPOLINE
+CFLAGS_REMOVE_sha256.o         += $(RETPOLINE_CFLAGS)
+CFLAGS_REMOVE_purgatory.o      += $(RETPOLINE_CFLAGS)
+CFLAGS_REMOVE_string.o         += $(RETPOLINE_CFLAGS)
+CFLAGS_REMOVE_kexec-purgatory.o        += $(RETPOLINE_CFLAGS)
+endif
 
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
index 6d8d5a3..b607bda 100644 (file)
@@ -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 (file)
index 01ad438..0000000
+++ /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);
-}
index 60c2200..80828b9 100644 (file)
@@ -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>
index 7286032..b33be92 100644 (file)
@@ -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
index 24ed269..55a7dc2 100644 (file)
@@ -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");
index d973c38..0fff7b5 100644 (file)
@@ -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);
 
index cf22ab0..126021f 100644 (file)
@@ -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;
index b038ec6..f78d328 100644 (file)
@@ -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)) {
@@ -1960,9 +1958,13 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
        rq = blk_mq_get_request(q, bio, &data);
        if (unlikely(!rq)) {
                rq_qos_cleanup(q, bio);
-               if (bio->bi_opf & REQ_NOWAIT)
+
+               cookie = BLK_QC_T_NONE;
+               if (bio->bi_opf & REQ_NOWAIT_INLINE)
+                       cookie = BLK_QC_T_EAGAIN;
+               else if (bio->bi_opf & REQ_NOWAIT)
                        bio_wouldblock_error(bio);
-               return BLK_QC_T_NONE;
+               return cookie;
        }
 
        trace_block_getrq(q, bio, bio->bi_opf);
index 659ccb8..3954c0d 100644 (file)
@@ -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);
 }
index 2ae348c..2c18312 100644 (file)
@@ -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);
 
index 97887e5..54f1f0d 100644 (file)
@@ -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)
index d4551e3..8569b79 100644 (file)
@@ -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;
        }
index 28cffaa..f616b16 100644 (file)
@@ -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. */
index c02fa27..1413324 100644 (file)
@@ -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[] = {
index 6ee2b02..2424194 100644 (file)
@@ -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);
index 0e28270..aad6be5 100644 (file)
@@ -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.
index 38a59a6..dc1c83e 100644 (file)
@@ -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)) {
index 72312ad..9e9583a 100644 (file)
@@ -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;
        }
index 391ac05..76d0f9d 100644 (file)
@@ -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");
index 10aa278..4f115ad 100644 (file)
@@ -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;
        }
 }
index 173e6f2..eefda51 100644 (file)
@@ -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 */
index 7c37f2f..deae466 100644 (file)
@@ -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);
 
index 302cf0b..8c7a996 100644 (file)
@@ -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:
index da84a73..1669d41 100644 (file)
@@ -1663,6 +1663,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 +1823,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 +2265,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 +2302,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
index 7048a41..7ecd590 100644 (file)
@@ -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 */
index 506a017..ec974ba 100644 (file)
@@ -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
index 5b49f1b..e2ea235 100644 (file)
@@ -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);
        }
index 85f20e3..bd7d3bb 100644 (file)
@@ -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 */
index 90ebfca..2b3103c 100644 (file)
@@ -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;
 }
index 44c9985..ab7ca59 100644 (file)
@@ -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:
index 9bcde23..e21d2de 100644 (file)
@@ -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))
index a55be20..dbfe346 100644 (file)
@@ -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;
index 8905ad2..ae2624f 100644 (file)
@@ -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;
index 207bae5..31f2515 100644 (file)
@@ -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;
index 8950e07..85a30fb 100644 (file)
@@ -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)
 {
index f98e5cc..fbc3f7c 100644 (file)
@@ -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;
index 9a5c9c1..82a0a36 100644 (file)
@@ -473,6 +473,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;
index f11af39..6ab6311 100644 (file)
@@ -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);
index 5c39f20..9ac6671 100644 (file)
@@ -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
index 5720433..285e0b8 100644 (file)
@@ -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));
 
index d47ad10..4838c6a 100644 (file)
@@ -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);
 
@@ -545,6 +554,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 +587,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;
index e503ffc..a7fea3e 100644 (file)
@@ -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);
index faacbe1..149e953 100644 (file)
@@ -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;
+}
index d103545..ba9acae 100644 (file)
@@ -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:
index 44db83a..44a46dc 100644 (file)
@@ -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);
index c099070..c11b178 100644 (file)
@@ -2487,6 +2487,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
index 0eaf418..1ac0c79 100644 (file)
@@ -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
index 05641c6..77a3d71 100644 (file)
@@ -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
 
index 6b8e75d..43fa9c3 100644 (file)
@@ -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 (file)
index 0000000..07481a5
--- /dev/null
@@ -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);
index fb6edf1..c0aff7c 100644 (file)
@@ -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 = {
index f628071..cfc05e4 100644 (file)
 
 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)
 {
index d94d9cb..bb4ec1b 100644 (file)
@@ -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);
 
index 1aa5f40..73b7e23 100644 (file)
@@ -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)
index a6b20e1..dabeb43 100644 (file)
@@ -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
index bc35a4e..3939f21 100644 (file)
@@ -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
index 0086f31..b488b40 100644 (file)
@@ -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[] = {
index 8028ff6..741df7e 100644 (file)
@@ -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;
index 3ddd0ef..13fc000 100644 (file)
@@ -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 (file)
index 0000000..3697692
--- /dev/null
@@ -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 (file)
index 0000000..f490840
--- /dev/null
@@ -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 (file)
index 086226e..0000000
+++ /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 (file)
index 4a541b9..0000000
+++ /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 */
index 1dd0abe..c4a3960 100644 (file)
@@ -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 */
index 1994e73..6249956 100644 (file)
@@ -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[] = {
index db1c4ed..c3f0ffc 100644 (file)
 #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,
index c8aed31..559a34c 100644 (file)
 #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
index 449f6ac..e940861 100644 (file)
@@ -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[] = {
index dab16d9..7cfb998 100644 (file)
 #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);
index b679519..bf8bea6 100644 (file)
@@ -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;
index 999cde3..605b438 100644 (file)
 
 #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;
 };
 
index 6ba2094..a7cb1e7 100644 (file)
@@ -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;
index 9ab5d6f..7731620 100644 (file)
@@ -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 {
index 537219f..67e6691 100644 (file)
@@ -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);
index 52bbb9c..d4075b1 100644 (file)
@@ -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;
 }
 
index 91d3d72..3c219af 100644 (file)
@@ -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
 
index 5e6038f..09e0311 100644 (file)
@@ -55,7 +55,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 +92,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 +111,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);
index 23553ed..2d22d6b 100644 (file)
@@ -248,16 +248,12 @@ static int __maybe_unused cn_proc_show(struct seq_file *m, void *v)
        return 0;
 }
 
-static struct cn_dev cdev = {
-       .input   = cn_rx_skb,
-};
-
 static int cn_init(void)
 {
        struct cn_dev *dev = &cdev;
        struct netlink_kernel_cfg cfg = {
                .groups = CN_NETLINK_USERS + 0xf,
-               .input  = dev->input,
+               .input  = cn_rx_skb,
        };
 
        dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, &cfg);
index 93f39a1..c66f566 100644 (file)
@@ -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:
index f9fec2d..94c1ad7 100644 (file)
@@ -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;
index c69ed4b..9bc3c62 100644 (file)
@@ -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:
index ece83a3..f22f6fa 100644 (file)
@@ -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);
index 3dc1cbf..b785e93 100644 (file)
@@ -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;
                }
index 42566b7..df8a56a 100644 (file)
@@ -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--;
index 46bd22d..94a13fc 100644 (file)
@@ -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)++;
index 53446e3..ba8d3d0 100644 (file)
@@ -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
index ab3aa39..7e12cbd 100644 (file)
@@ -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;
index 474f304..cdd4f73 100644 (file)
@@ -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.
index 3ee99d0..f497003 100644 (file)
@@ -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);
@@ -1392,12 +1394,17 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        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);
index 1d80222..3c88420 100644 (file)
@@ -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
index 1d3ee9c..6a5c96e 100644 (file)
@@ -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;
index e069de8..4e4094f 100644 (file)
@@ -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;
 }
index 6d54dec..5652cc7 100644 (file)
@@ -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;
 
index f2e8b42..5376328 100644 (file)
@@ -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)
index df8a235..f6ac1e9 100644 (file)
@@ -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 {
index 8b7efd0..2b54656 100644 (file)
@@ -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);
+                       }
                }
        }
 
index 1a4412e..fac7aa2 100644 (file)
@@ -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);
index 99f14fc..19661c6 100644 (file)
@@ -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
index 1675d58..f41287f 100644 (file)
@@ -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;
        }
 
index 0db9f48..2118727 100644 (file)
@@ -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)
index 5f401b4..ee1ccdc 100644 (file)
@@ -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;
 }
 
index f4c4eea..1cf639a 100644 (file)
@@ -1918,6 +1918,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)
index 988c0ad..dfde886 100644 (file)
@@ -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,
index 26b15cc..1d3cd5c 100644 (file)
@@ -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)
index 7923714..4e3fc28 100644 (file)
@@ -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);
index 4f8a6ff..9cd3eb2 100644 (file)
@@ -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;
index c1a92c1..5cc3acc 100644 (file)
@@ -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;
index 778392c..7c746ef 100644 (file)
@@ -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;
index 906310c..5399b8c 100644 (file)
@@ -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;
 }
index 08a774f..50bfb59 100644 (file)
@@ -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;
index 4ef4dc6..fa20201 100644 (file)
@@ -502,8 +502,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);
 
index 8dbf759..355b4ba 100644 (file)
@@ -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++) {
index 056be4c..2c7aaed 100644 (file)
@@ -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(
index 51a7828..2ceaab4 100644 (file)
@@ -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);
 
index af7f8be..3528623 100644 (file)
@@ -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;
index f8903bc..58bd131 100644 (file)
@@ -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)
index 858a588..fafb4b4 100644 (file)
@@ -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;
        }
 }
 
index e50a696..2118ea2 100644 (file)
@@ -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);
 }
index 1a20461..a12530a 100644 (file)
@@ -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 = {
index 51a3dfe..31aa6ee 100644 (file)
@@ -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;
index ece6e13..6e2dbd0 100644 (file)
@@ -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);
        }
index 0b84a32..d810c89 100644 (file)
@@ -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
index 26a66cc..1ae9739 100644 (file)
@@ -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;
 }
index d200bc3..b949e20 100644 (file)
@@ -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;
index 27679ef..96c2632 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#include <linux/delay.h>
+
 #include "dcn20_vmid.h"
 #include "reg_helper.h"
 
 #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);
 }
index 6708976..340ef4d 100644 (file)
@@ -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);
index c89393c..a148ffd 100644 (file)
@@ -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;
 
index 959f5b6..9502478 100644 (file)
@@ -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 {
index 8759ec0..f82365e 100644 (file)
@@ -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
index 1c66166..2c90d1b 100644 (file)
@@ -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) */
 };
 
index 9f661bf..5b1ebb7 100644 (file)
@@ -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 {
index f1565c4..8a3eade 100644 (file)
@@ -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;
        }
index e32ae9d..18e780f 100644 (file)
@@ -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;
        }
 }
 
index 1af992f..a0f52c8 100644 (file)
@@ -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)
@@ -918,6 +919,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,
index 2dae0ae..b81c7e7 100644 (file)
@@ -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)
index 957288e..620ff17 100644 (file)
 #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
index 95c7c4d..5fde5cf 100644 (file)
@@ -1124,10 +1124,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 +1136,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 +1147,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 +1187,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 +1206,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 +1377,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 +1391,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 +1762,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,
index bb9bb09..dd6fd1c 100644 (file)
@@ -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;
 
@@ -3217,35 +3233,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 +3298,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
 };
index bc19dbd..359030d 100644 (file)
@@ -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;
index ee77746..e4e22bb 100644 (file)
@@ -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.
 
index 410572f..e1dafb0 100644 (file)
@@ -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)
 {
index 56d3677..c8922b7 100644 (file)
@@ -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;
index 1984e5c..a7ba5b4 100644 (file)
@@ -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;
index 0b72468..5756431 100644 (file)
@@ -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;
index 74a5739..b0369e6 100644 (file)
@@ -1686,7 +1686,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.
@@ -1770,7 +1770,9 @@ 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;
+               strscpy(mode->name, name, mode_end + 1);
        } else {
                ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
                                                      parse_extras,
index 60ce4a8..6f7d3b3 100644 (file)
@@ -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
index a594ab7..164d914 100644 (file)
@@ -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,
index 50904ee..2a3382d 100644 (file)
@@ -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;
index 1e4b21c..1c524db 100644 (file)
@@ -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))
 
index 9af0964..b24ba94 100644 (file)
@@ -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;
 }
index 91355c2..8cace65 100644 (file)
@@ -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)
index c471088..3ef4e9f 100644 (file)
@@ -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) {
index 753ac31..7b908e1 100644 (file)
@@ -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];
        }
index 8993ab2..0d19bbd 100644 (file)
@@ -2239,6 +2239,17 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
        if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9)
                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.
index 8592a7d..592b927 100644 (file)
@@ -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:
index c93ad51..2d1939d 100644 (file)
@@ -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);
 
index 4336df4..d0fc348 100644 (file)
@@ -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:
index bc3a94d..27bd727 100644 (file)
@@ -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;
        }
 
        /*
index 2f4894e..5ddbe71 100644 (file)
@@ -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;
 
 /*
index 99cc3e2..f016a77 100644 (file)
@@ -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 */
index 5fae0e5..41dab9e 100644 (file)
@@ -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);
        }
index 391621e..39a6619 100644 (file)
@@ -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
index b36ad26..65eb430 100644 (file)
@@ -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;
index 05011d4..914b5d4 100644 (file)
@@ -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);
index 528b616..2caa594 100644 (file)
@@ -664,7 +664,15 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
 
        for_each_sgt_page(page, sgt_iter, pages) {
                if (obj->mm.dirty)
-                       set_page_dirty(page);
+                       /*
+                        * As this may not be anonymous memory (e.g. shmem)
+                        * but exist on a real mapping, we have to lock
+                        * the page in order to dirty it -- holding
+                        * the page reference is not sufficient to
+                        * prevent the inode from being truncated.
+                        * Play safe and take the lock.
+                        */
+                       set_page_dirty_lock(page);
 
                mark_page_accessed(page);
                put_page(page);
index 2c454f2..2312090 100644 (file)
@@ -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)
index 7fd33e8..f25632c 100644 (file)
@@ -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;
 }
index 2ce00d3..ae5b6ba 100644 (file)
@@ -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;
-}
index b326cd9..a11c893 100644 (file)
@@ -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 */
index 868b220..43e975a 100644 (file)
@@ -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;
index 7b59677..9f8f7f5 100644 (file)
@@ -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;
 }
index 7dd1130..53f342b 100644 (file)
@@ -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 */
index b42b5f1..82b7ace 100644 (file)
@@ -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:
index 4c478b3..3f90770 100644 (file)
@@ -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;
 }
 
index c6023bc..12010e7 100644 (file)
@@ -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);
 }
 
index 15e90fd..98dfb08 100644 (file)
@@ -1098,10 +1098,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 +1144,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 +1286,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)) {
index 086801b..486c695 100644 (file)
@@ -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);
index 89da9e7..b5c590c 100644 (file)
@@ -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);
index 9eaf030..44becd9 100644 (file)
@@ -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;
        }
 
index 6ea8827..b09dc31 100644 (file)
@@ -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;
index 65e8473..8bb292b 100644 (file)
@@ -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);
index 53115bd..4b04af5 100644 (file)
@@ -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);
index 144301b..23aa3e5 100644 (file)
@@ -1904,6 +1904,18 @@ static int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
 
        entry = __gvt_cache_find_gfn(info->vgpu, gfn);
        if (!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 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;
index 2144fb4..9f3fd7d 100644 (file)
@@ -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)) {
+                               kmem_cache_free(s->workloads, workload);
+                               gvt_vgpu_err("invalid wa_ctx at: 0x%lx\n",
+                                   workload->wa_ctx.indirect_ctx.guest_gma);
+                               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)) {
+                               kmem_cache_free(s->workloads, workload);
+                               gvt_vgpu_err("invalid per_ctx at: 0x%lx\n",
+                                       workload->wa_ctx.per_ctx.guest_gma);
+                               return ERR_PTR(-EINVAL);
+                       }
+               }
        }
 
        gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n",
index a3deed6..fe552e8 100644 (file)
@@ -28,8 +28,6 @@
  *
  */
 
-#include "trace.h"
-
 #ifndef __CHECKER__
 #define CREATE_TRACE_POINTS
 #include "trace.h"
index bc909ec..fe7a6ec 100644 (file)
@@ -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;
index 190ad54..8a659d3 100644 (file)
@@ -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);
index 8ab8201..7015a97 100644 (file)
@@ -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:
index b7e9fdd..8bc76fc 100644 (file)
@@ -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,
index a700c5c..5140017 100644 (file)
@@ -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);
                }
        }
index f4ce643..cce426b 100644 (file)
 /* 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;
index 502c544..8d1aebc 100644 (file)
@@ -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);
 }
index 9cbb2eb..3827531 100644 (file)
@@ -65,6 +65,21 @@ intel_wakeref_get(struct intel_runtime_pm *rpm,
        return 0;
 }
 
+/**
+ * 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
index 1671db4..e9c55d1 100644 (file)
@@ -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));
index be39cf0..dc8ec2c 100644 (file)
@@ -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));
index 9acbbc0..048c8be 100644 (file)
@@ -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);
index 0e2f741..0aa8a12 100644 (file)
@@ -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;
index ff14555..78d5fa2 100644 (file)
@@ -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 = {
index 4a60f5f..fec6ef1 100644 (file)
@@ -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;
index ab64ab4..c356f5c 100644 (file)
@@ -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);
 
index 8b78554..8cf6362 100644 (file)
@@ -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);
index 8497768..1267038 100644 (file)
@@ -780,7 +780,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
                        drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock,
                                             connector->display_info.bpc * 3);
 
-       if (drm_atomic_crtc_needs_modeset(crtc_state)) {
+       if (crtc_state->mode_changed) {
                slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
                                                      mstc->port,
                                                      asyh->dp.pbn);
index 8c92374..a835ceb 100644 (file)
@@ -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.
index 95e5c51..9aae3d8 100644 (file)
@@ -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
 };
index 274cb95..bdcaa4c 100644 (file)
@@ -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);
index d594f75..7d78e6d 100644 (file)
@@ -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;
index e4e09d4..59e9d05 100644 (file)
@@ -389,8 +389,10 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
                break;
        }
 
-       if (retries == RETRIES)
+       if (retries == RETRIES) {
+               kfree(reply);
                return -EINVAL;
+       }
 
        *msg_len = reply_len;
        *msg     = reply;
index 98bf694..3a8c4a5 100644 (file)
 #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,
index b3d5024..0a38e8e 100644 (file)
@@ -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,
index 0d695f8..0a00be1 100644 (file)
 #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
 #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
 #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
index 6196217..cc47f94 100644 (file)
@@ -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),
index e3b6245..21268c9 100644 (file)
@@ -3749,15 +3749,45 @@ static const struct hid_device_id hidpp_devices[] = {
 
        { L27MHZ_DEVICE(HID_ANY_ID) },
 
-       { /* Logitech G403 Gaming Mouse over USB */
+       { /* Logitech G203/Prodigy Gaming Mouse */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC084) },
+       { /* Logitech G302 Gaming Mouse */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07F) },
+       { /* Logitech G303 Gaming Mouse */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC080) },
+       { /* Logitech G400 Gaming Mouse */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07E) },
+       { /* Logitech G403 Wireless Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
+       { /* Logitech G403 Gaming Mouse */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC083) },
+       { /* Logitech G403 Hero Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08F) },
+       { /* Logitech G502 Proteus Core Gaming Mouse */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07D) },
+       { /* Logitech G502 Proteus Spectrum Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC332) },
+       { /* Logitech G502 Hero Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08B) },
        { /* Logitech G700 Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC06B) },
+       { /* Logitech G700s Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07C) },
+       { /* 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),
index 185a577..166f41f 100644 (file)
@@ -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 },
index 9394206..49dd2d9 100644 (file)
@@ -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)
 {
index e12f258..bdfc5ff 100644 (file)
@@ -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) */
index 55b7257..4e11cc6 100644 (file)
@@ -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);
index 8fc36a2..7a8ddc9 100644 (file)
@@ -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) {
index 3fb9c0a..ce5ec40 100644 (file)
@@ -343,7 +343,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                data->sample_time = MSEC_PER_SEC / 2;
                break;
        case tmp75b:  /* not one-shot mode, Conversion rate 37Hz */
-               clr_mask |= 1 << 15 | 0x3 << 13;
+               clr_mask |= 1 << 7 | 0x3 << 5;
                data->resolution = 12;
                data->sample_time = MSEC_PER_SEC / 37;
                break;
index e7dff5f..d42bc08 100644 (file)
@@ -852,7 +852,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 };
 
@@ -3764,6 +3764,7 @@ 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_TOLERANCE_H = NCT6106_REG_TOLERANCE_H;
                data->REG_PWM[0] = NCT6106_REG_PWM;
                data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
                data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
index ec7bcf8..f3dd2a1 100644 (file)
@@ -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;
index a7d2b16..30e18eb 100644 (file)
@@ -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,
index 5c1ca0d..84f1dcb 100644 (file)
@@ -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;
index 8d55cdd..435c7d7 100644 (file)
@@ -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,
index e87232f..a3fcc35 100644 (file)
@@ -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));
                }
        }
 
index 2c7f145..d7fd76b 100644 (file)
@@ -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++;
        }
 }
index cfc76b5..5a1235f 100644 (file)
@@ -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)
 {
index d97fb85..c98ef4c 100644 (file)
@@ -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:
                /*
index 46bb2e4..ad19d9c 100644 (file)
@@ -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,              \
index 92b1d50..e234970 100644 (file)
@@ -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>
 #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);
index 917223d..0e3c652 100644 (file)
@@ -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
index 2d68573..c37f201 100644 (file)
@@ -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. */
index 53a5995..8a704cd 100644 (file)
@@ -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;
index 888d89c..beee7b7 100644 (file)
@@ -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);
index 01faef7..45d5164 100644 (file)
@@ -393,6 +393,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];
 
@@ -594,7 +597,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 +605,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 +630,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);
index 9773145..ea8661a 100644 (file)
@@ -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.
@@ -660,6 +666,14 @@ static int add_client_context(struct ib_device *device,
                return 0;
 
        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);
 
index cc99479..9947d16 100644 (file)
@@ -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 */
index 9f8a480..ffdeaf6 100644 (file)
@@ -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;
        }
index a91653a..098ab88 100644 (file)
@@ -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);
index 37928b1..bdbde8e 100644 (file)
@@ -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);
 }
 
index 30c42c9..fbda11a 100644 (file)
@@ -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;
index 48793d3..40296b9 100644 (file)
@@ -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;
index 0ec3b12..13d9432 100644 (file)
@@ -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);
index d5b643a..67052dc 100644 (file)
@@ -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 */
index 0477c14..024a7c2 100644 (file)
@@ -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,
index 92accca..996fc29 100644 (file)
@@ -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,
@@ -2788,19 +2761,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);
index c4b243f..646f615 100644 (file)
@@ -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)
index 8bf847b..5478219 100644 (file)
@@ -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.
index e105945..449a2d8 100644 (file)
@@ -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
index 627aa46..c00714c 100644 (file)
@@ -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);
 
index 81e6ded..c07e387 100644 (file)
@@ -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);
index c2a5780..e12a440 100644 (file)
@@ -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);
 
index c482f19..f6a5345 100644 (file)
@@ -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)
index 20ece6e..b74fad0 100644 (file)
@@ -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,30 @@ 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_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled) &&
+                 (!MLX5_CAP_GEN(dev->mdev, umr_modify_atomic_disabled) ||
+                  !MLX5_CAP_GEN(dev->mdev, atomic));
+
+       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 +1332,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 +1367,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);
 }
@@ -1577,10 +1573,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)
index 5b642d8..81da820 100644 (file)
@@ -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
@@ -1771,7 +1772,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 +1814,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);
 
index 2a97619..379328b 100644 (file)
@@ -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;
        }
@@ -4295,10 +4294,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) {
index 533157a..f97b3d6 100644 (file)
@@ -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);
 
index a7cde98..9ce8a1b 100644 (file)
@@ -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;
index f55c4e8..d0f140d 100644 (file)
@@ -612,6 +612,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;
        }
        /*
index 11383d9..e27bd5b 100644 (file)
@@ -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) {
index 29abfee..6c554c1 100644 (file)
@@ -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)
index 8e9c3ea..90e8a7f 100644 (file)
@@ -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,*.
index 548737e..584289b 100644 (file)
@@ -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,
 };
index 2d8434b..04fe434 100644 (file)
@@ -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;
index b1956ed..46bbe99 100644 (file)
@@ -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
 };
 
index 04b8557..aa57789 100644 (file)
@@ -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,
index a2cec6c..16d7020 100644 (file)
@@ -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)
index eb104c7..4413aa6 100644 (file)
@@ -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>
@@ -1920,6 +1922,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 +2022,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)
index 52c35d5..64edd5a 100644 (file)
 #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
 #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)
index 73a5529..2b25d9c 100644 (file)
@@ -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,
index ac4172c..bdaed2d 100644 (file)
@@ -339,8 +339,6 @@ static void domain_exit(struct dmar_domain *domain);
 static void domain_remove_dev_info(struct dmar_domain *domain);
 static void dmar_remove_one_dev_info(struct device *dev);
 static void __dmar_remove_one_dev_info(struct device_domain_info *info);
-static void domain_context_clear(struct intel_iommu *iommu,
-                                struct device *dev);
 static int domain_detach_iommu(struct dmar_domain *domain,
                               struct intel_iommu *iommu);
 static bool device_is_rmrr_locked(struct device *dev);
@@ -1833,9 +1831,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 +1897,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);
 }
@@ -2048,26 +2105,9 @@ out_unlock:
        return ret;
 }
 
-struct domain_context_mapping_data {
-       struct dmar_domain *domain;
-       struct intel_iommu *iommu;
-       struct pasid_table *table;
-};
-
-static int domain_context_mapping_cb(struct pci_dev *pdev,
-                                    u16 alias, void *opaque)
-{
-       struct domain_context_mapping_data *data = opaque;
-
-       return domain_context_mapping_one(data->domain, data->iommu,
-                                         data->table, PCI_BUS_NUM(alias),
-                                         alias & 0xff);
-}
-
 static int
 domain_context_mapping(struct dmar_domain *domain, struct device *dev)
 {
-       struct domain_context_mapping_data data;
        struct pasid_table *table;
        struct intel_iommu *iommu;
        u8 bus, devfn;
@@ -2077,17 +2117,7 @@ domain_context_mapping(struct dmar_domain *domain, struct device *dev)
                return -ENODEV;
 
        table = intel_pasid_get_table(dev);
-
-       if (!dev_is_pci(dev))
-               return domain_context_mapping_one(domain, iommu, table,
-                                                 bus, devfn);
-
-       data.domain = domain;
-       data.iommu = iommu;
-       data.table = table;
-
-       return pci_for_each_dma_alias(to_pci_dev(dev),
-                                     &domain_context_mapping_cb, &data);
+       return domain_context_mapping_one(domain, iommu, table, bus, devfn);
 }
 
 static int domain_context_mapped_cb(struct pci_dev *pdev,
@@ -2513,31 +2543,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 +2580,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 +2689,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 +2701,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;
        }
@@ -3564,7 +3563,8 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
 
        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 */
@@ -4758,28 +4758,6 @@ out_free_dmar:
        return ret;
 }
 
-static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
-{
-       struct intel_iommu *iommu = opaque;
-
-       domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
-       return 0;
-}
-
-/*
- * NB - intel-iommu lacks any sort of reference counting for the users of
- * dependent devices.  If multiple endpoints have intersecting dependent
- * devices, unbinding the driver from any one of them will possibly leave
- * the others unable to operate.
- */
-static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
-{
-       if (!iommu || !dev || !dev_is_pci(dev))
-               return;
-
-       pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
-}
-
 static void __dmar_remove_one_dev_info(struct device_domain_info *info)
 {
        struct dmar_domain *domain;
@@ -4800,7 +4778,7 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
                                        PASID_RID2PASID);
 
                iommu_disable_dev_iotlb(info);
-               domain_context_clear(iommu, info->dev);
+               domain_context_clear_one(iommu, info->bus, info->devfn);
                intel_pasid_free_table(info->dev);
        }
 
@@ -4829,6 +4807,31 @@ static void dmar_remove_one_dev_info(struct device *dev)
        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 +4846,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;
index d499b26..3e1a8a6 100644 (file)
@@ -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;
        }
index 433f4d2..80a740d 100644 (file)
@@ -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;
@@ -1027,7 +1036,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 +1048,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 +1066,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 +1147,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[] = {
index 730fbe0..1b5c367 100644 (file)
@@ -3010,7 +3010,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;
        }
 
index 9bca489..96d927f 100644 (file)
@@ -771,8 +771,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 +788,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);
index bf2237a..4f74c15 100644 (file)
@@ -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
index 3dd2838..3f09f65 100644 (file)
@@ -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;
index 0e22423..008a74a 100644 (file)
@@ -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;
index 276065c..23f1f41 100644 (file)
@@ -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;
index 26e374f..20ed838 100644 (file)
@@ -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;
        }
 
index 9f08267..e2059af 100644 (file)
@@ -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;
 
index caaee80..7b6c3ee 100644 (file)
@@ -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;
        }
 
@@ -1921,7 +1921,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
index bc2a176..d535aac 100644 (file)
@@ -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;
index 21fb90d..25c73c1 100644 (file)
@@ -124,7 +124,7 @@ static inline int check_which(__u32 which)
 static inline int check_pad(struct v4l2_subdev *sd, __u32 pad)
 {
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (sd->entity.graph_obj.mdev) {
+       if (sd->entity.num_pads) {
                if (pad >= sd->entity.num_pads)
                        return -EINVAL;
                return 0;
index 3f21e26..90e0f21 100644 (file)
@@ -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;
index 792b855..4798d9f 100644 (file)
@@ -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]))
index f880947..f2abe27 100644 (file)
@@ -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
index 35bf247..518945b 100644 (file)
@@ -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;
index 6ad83d5..f00d1c3 100644 (file)
@@ -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,
index cc8168b..ea2ca67 100644 (file)
@@ -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);
 
index 75294ec..a0e1817 100644 (file)
@@ -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) {
@@ -2864,7 +2864,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 +2946,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);
 
@@ -4449,7 +4450,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 +4485,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:
index 10da994..6a4c64b 100644 (file)
@@ -1062,9 +1062,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 +1085,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) \
index d74b182..6c01737 100644 (file)
@@ -81,6 +81,9 @@
 
 #define MEI_DEV_ID_ICP_LP     0x34E0  /* Ice 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
  */
index 7a2b354..57cb68f 100644 (file)
@@ -98,6 +98,9 @@ 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_MCC, MEI_ME_PCH12_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
+
        /* required last entry */
        {0, }
 };
index e327f80..7102e2e 100644 (file)
@@ -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);
 
index ed5cefb..89deb45 100644 (file)
@@ -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;
index faaaf52..eea52e2 100644 (file)
@@ -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;
                                }
index 2d736e4..ba9a63d 100644 (file)
@@ -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)
index b3a130a..1604f51 100644 (file)
@@ -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
index c391510..776a942 100644 (file)
@@ -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;
 
index e377b9b..d4e7e8b 100644 (file)
@@ -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 */
 
index 4041878..7d06e28 100644 (file)
@@ -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;
        }
index 3ddecf4..e55037c 100644 (file)
@@ -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
 
index 8e4a8ba..f5753ae 100644 (file)
@@ -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
index 6ee340a..83a4767 100644 (file)
@@ -624,6 +624,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 +696,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:
index 8a18f14..1dea1ba 100644 (file)
@@ -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;
index 59acf8e..a5dc5aa 100644 (file)
@@ -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) {
index 89fd965..902f855 100644 (file)
@@ -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);
index cff6bbd..b4e3caf 100644 (file)
@@ -14,8 +14,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
index a1f8fe1..e082d63 100644 (file)
@@ -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;
index 1622d31..8ca9fad 100644 (file)
@@ -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;
index 11c5bad..14a5fb3 100644 (file)
@@ -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];
        }
index 28510e3..cd27fdc 100644 (file)
@@ -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];
        }
index 2c54601..186bbf8 100644 (file)
@@ -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];
        }
index ca4a57c..bd75d06 100644 (file)
@@ -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];
        }
index 9b7016a..02fd782 100644 (file)
@@ -2196,6 +2196,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:
index 1d40759..c8e1a04 100644 (file)
@@ -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;
index b6b93a2..483d270 100644 (file)
@@ -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);
index f2fe344..fcec8bc 100644 (file)
@@ -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;
index 7f6a3b9..13b10cb 100644 (file)
@@ -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;
index 0541000..de34a4b 100644 (file)
@@ -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;
 }
index 185c7f7..5e0d5e8 100644 (file)
@@ -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);
 
index 44e99e3..12358f0 100644 (file)
@@ -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;
 }
index 15ce5ad..617da29 100644 (file)
@@ -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) {
index 458154c..65dce64 100644 (file)
@@ -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);
 
index 34761c3..47cc1ff 100644 (file)
@@ -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;
index 178bb7c..53cb2f7 100644 (file)
@@ -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;
 
index 6b17cd9..d0a97eb 100644 (file)
@@ -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,
index 232e8cc..16f15c9 100644 (file)
@@ -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;
 }
 
index 6bfb169..9988c9d 100644 (file)
@@ -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,
index 32bf3a7..d073baf 100644 (file)
@@ -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);
 
-       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_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,
@@ -1270,39 +1254,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 +1548,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 +1577,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 +1728,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 +2187,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;
 }
 
index d19cfdf..d8e8dd5 100644 (file)
@@ -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);
 }
 
index 2a3e245..a947857 100644 (file)
@@ -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
 
index ea34bcb..edbb4b3 100644 (file)
@@ -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;
 
index 3434730..0537df0 100644 (file)
@@ -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;
index de4950d..9f965cd 100644 (file)
@@ -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.
 
index fde7ae3..f78b9c8 100644 (file)
@@ -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
index 8b69d0d..6703960 100644 (file)
@@ -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;
index e9017ca..e24f5d2 100644 (file)
@@ -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
 
index b9c5cea..9483553 100644 (file)
@@ -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);
index 656ed80..e47ea92 100644 (file)
@@ -285,6 +285,9 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata)
        hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
        sw_cons = txdata->tx_pkt_cons;
 
+       /* Ensure subsequent loads occur after hw_cons */
+       smp_rmb();
+
        while (sw_cons != hw_cons) {
                u16 pkt_cons;
 
@@ -1931,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)
index 7134d2c..7070349 100644 (file)
@@ -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,
index a2b5780..d3a0b61 100644 (file)
@@ -1895,7 +1895,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);
index ad22554..acb0168 100644 (file)
@@ -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. */
index 20c09cc..60aa45b 100644 (file)
@@ -94,7 +94,7 @@ static int my3126_interrupt_handler(struct cphy *cphy)
        return cphy_cause_link_change;
 }
 
-static void my3216_poll(struct work_struct *work)
+static void my3126_poll(struct work_struct *work)
 {
        struct cphy *cphy = container_of(work, struct cphy, phy_update.work);
 
@@ -177,7 +177,7 @@ static struct cphy *my3126_phy_create(struct net_device *dev,
                return NULL;
 
        cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops);
-       INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll);
+       INIT_DELAYED_WORK(&cphy->phy_update, my3126_poll);
        cphy->bmsr = 0;
 
        return cphy;
index 1e82b9e..58f89f6 100644 (file)
@@ -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);
 
index 67202b6..4311ad9 100644 (file)
@@ -5561,7 +5561,6 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
                char name[IFNAMSIZ];
                u32 devcap2;
                u16 flags;
-               int pos;
 
                /* If we want to instantiate Virtual Functions, then our
                 * parent bridge's PCI-E needs to support Alternative Routing
@@ -5569,9 +5568,8 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
                 * and above.
                 */
                pbridge = pdev->bus->self;
-               pos = pci_find_capability(pbridge, PCI_CAP_ID_EXP);
-               pci_read_config_word(pbridge, pos + PCI_EXP_FLAGS, &flags);
-               pci_read_config_dword(pbridge, pos + PCI_EXP_DEVCAP2, &devcap2);
+               pcie_capability_read_word(pbridge, PCI_EXP_FLAGS, &flags);
+               pcie_capability_read_dword(pbridge, PCI_EXP_DEVCAP2, &devcap2);
 
                if ((flags & PCI_EXP_FLAGS_VERS) < 2 ||
                    !(devcap2 & PCI_EXP_DEVCAP2_ARI)) {
index 312599c..e447976 100644 (file)
@@ -67,7 +67,8 @@ static struct ch_tc_pedit_fields pedits[] = {
 static struct ch_tc_flower_entry *allocate_flower_entry(void)
 {
        struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
-       spin_lock_init(&new->lock);
+       if (new)
+               spin_lock_init(&new->lock);
        return new;
 }
 
index 9dd5ed9..f7fc553 100644 (file)
@@ -7309,7 +7309,6 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
        } else {
                unsigned int pack_align;
                unsigned int ingpad, ingpack;
-               unsigned int pcie_cap;
 
                /* T5 introduced the separation of the Free List Padding and
                 * Packing Boundaries.  Thus, we can select a smaller Padding
@@ -7334,8 +7333,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                 * multiple of the Maximum Payload Size.
                 */
                pack_align = fl_align;
-               pcie_cap = pci_find_capability(adap->pdev, PCI_CAP_ID_EXP);
-               if (pcie_cap) {
+               if (pci_is_pcie(adap->pdev)) {
                        unsigned int mps, mps_log;
                        u16 devctl;
 
@@ -7343,9 +7341,8 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                         * [bits 7:5] encodes sizes as powers of 2 starting at
                         * 128 bytes.
                         */
-                       pci_read_config_word(adap->pdev,
-                                            pcie_cap + PCI_EXP_DEVCTL,
-                                            &devctl);
+                       pcie_capability_read_word(adap->pdev, PCI_EXP_DEVCTL,
+                                                 &devctl);
                        mps_log = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5) + 7;
                        mps = 1 << mps_log;
                        if (mps > pack_align)
index ef5d61d..323976c 100644 (file)
@@ -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;
index b7a246b..4d8e40a 100644 (file)
@@ -4698,8 +4698,13 @@ int be_update_queues(struct be_adapter *adapter)
        int status;
 
        if (netif_running(netdev)) {
+               /* be_tx_timeout() must not run concurrently with this
+                * function, synchronize with an already-running dev_watchdog
+                */
+               netif_tx_lock_bh(netdev);
                /* device cannot transmit now, avoid dev_watchdog timeouts */
                netif_carrier_off(netdev);
+               netif_tx_unlock_bh(netdev);
 
                be_close(netdev);
        }
@@ -5625,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;
        }
 
index ed0d010..04a59db 100644 (file)
@@ -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.
index e80fedb..210749b 100644 (file)
@@ -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);
index 92372dc..ebc37e2 100644 (file)
@@ -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 */
index 26540b8..d8fa816 100644 (file)
@@ -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;
index 1914b83..59564ac 100644 (file)
@@ -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 */
index d604528..c841674 100644 (file)
@@ -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);
index 8ad5292..75329ab 100644 (file)
@@ -43,7 +43,7 @@ enum HCLGE_MBX_OPCODE {
        HCLGE_MBX_GET_QID_IN_PF,        /* (VF -> PF) get queue id in pf */
        HCLGE_MBX_LINK_STAT_MODE,       /* (PF -> VF) link mode has changed */
        HCLGE_MBX_GET_LINK_MODE,        /* (VF -> PF) get the link mode of pf */
-       HLCGE_MBX_PUSH_VLAN_INFO,       /* (PF -> VF) push port base vlan */
+       HCLGE_MBX_PUSH_VLAN_INFO,       /* (PF -> VF) push port base vlan */
        HCLGE_MBX_GET_MEDIA_TYPE,       /* (VF -> PF) get media type */
 
        HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
index a38ac7c..690b999 100644 (file)
@@ -304,7 +304,7 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
        memcpy(&msg_data[6], &vlan_tag, sizeof(u16));
 
        return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
-                                 HLCGE_MBX_PUSH_VLAN_INFO, vfid);
+                                 HCLGE_MBX_PUSH_VLAN_INFO, vfid);
 }
 
 static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
index f60b80b..6a96987 100644 (file)
@@ -204,7 +204,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
                case HCLGE_MBX_LINK_STAT_CHANGE:
                case HCLGE_MBX_ASSERTING_RESET:
                case HCLGE_MBX_LINK_STAT_MODE:
-               case HLCGE_MBX_PUSH_VLAN_INFO:
+               case HCLGE_MBX_PUSH_VLAN_INFO:
                        /* set this mbx event as pending. This is required as we
                         * might loose interrupt event when mbx task is busy
                         * handling. This shall be cleared when mbx task just
@@ -307,7 +307,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
                        hclgevf_reset_task_schedule(hdev);
 
                        break;
-               case HLCGE_MBX_PUSH_VLAN_INFO:
+               case HCLGE_MBX_PUSH_VLAN_INFO:
                        state = le16_to_cpu(msg_q[1]);
                        vlan_info = &msg_q[1];
                        hclgevf_update_port_base_vlan_info(hdev, state,
index 4138a84..cca71ba 100644 (file)
@@ -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");
index 93f3b4e..aa9323e 100644 (file)
@@ -3912,13 +3912,11 @@ void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value)
 s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
 {
        struct igc_adapter *adapter = hw->back;
-       u16 cap_offset;
 
-       cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
-       if (!cap_offset)
+       if (!pci_is_pcie(adapter->pdev))
                return -IGC_ERR_CONFIG;
 
-       pci_read_config_word(adapter->pdev, cap_offset + reg, value);
+       pcie_capability_read_word(adapter->pdev, reg, value);
 
        return IGC_SUCCESS;
 }
@@ -3926,13 +3924,11 @@ s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
 s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
 {
        struct igc_adapter *adapter = hw->back;
-       u16 cap_offset;
 
-       cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
-       if (!cap_offset)
+       if (!pci_is_pcie(adapter->pdev))
                return -IGC_ERR_CONFIG;
 
-       pci_write_config_word(adapter->pdev, cap_offset + reg, *value);
+       pcie_capability_write_word(adapter->pdev, reg, *value);
 
        return IGC_SUCCESS;
 }
index f660cc2..0b9e851 100644 (file)
@@ -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 &&
index c51f1d5..ccdd47f 100644 (file)
@@ -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];
 
index f518312..a01c75e 100644 (file)
@@ -4924,6 +4924,13 @@ 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"),
+               },
+       },
        {}
 };
 
index 263cd09..1f7fff8 100644 (file)
@@ -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
index 5bb6a26..5086227 100644 (file)
@@ -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);
index 79d93d6..ce1be2a 100644 (file)
@@ -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,14 +182,6 @@ 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;
@@ -830,6 +822,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 +864,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);
index bd882b5..3a615d6 100644 (file)
@@ -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 */
index d5e5afb..f777994 100644 (file)
@@ -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);
index 70f536e..4a7f449 100644 (file)
@@ -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);
index ea032f5..3766545 100644 (file)
@@ -412,7 +412,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);
index 126ec41..03bed71 100644 (file)
@@ -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,69 @@ 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);
 
        link_modes = link_modes & eproto.cap;
        if (!link_modes) {
@@ -1067,14 +1092,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:
index ea3a490..94304ab 100644 (file)
@@ -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)) {
index 47eea6b..6c712c5 100644 (file)
@@ -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];
@@ -1677,10 +1676,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 +2437,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 +2458,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 +2554,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 +2755,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 +2855,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 +2880,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 +3302,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 +3314,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 +3353,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 +3481,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 +4954,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 +5157,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 +5175,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 +5213,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;
index 7245d28..d0684fd 100644 (file)
@@ -735,8 +735,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
                list_add(&indr_priv->list,
                         &rpriv->uplink_priv.tc_indr_block_priv_list);
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              mlx5e_rep_indr_setup_block_cb,
+               block_cb = flow_block_cb_alloc(mlx5e_rep_indr_setup_block_cb,
                                               indr_priv, indr_priv,
                                               mlx5e_rep_indr_tc_block_unbind);
                if (IS_ERR(block_cb)) {
@@ -753,7 +752,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
                if (!indr_priv)
                        return -ENOENT;
 
-               block_cb = flow_block_cb_lookup(f,
+               block_cb = flow_block_cb_lookup(f->block,
                                                mlx5e_rep_indr_setup_block_cb,
                                                indr_priv);
                if (!block_cb)
@@ -1702,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 = {
@@ -1719,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
index 539b4d3..57f9f34 100644 (file)
@@ -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++)
index cc096f6..7ecfc53 100644 (file)
@@ -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;
index c50b6f0..49b06b2 100644 (file)
@@ -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;
index c48c382..c1252d6 100644 (file)
@@ -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
index b376212..1834d9f 100644 (file)
@@ -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)
 {
index 6bfaaab..1a2560e 100644 (file)
@@ -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 */
index 6e56fa7..c5a491e 100644 (file)
@@ -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)
index 4d34d42..eda9c23 100644 (file)
@@ -1604,14 +1604,14 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
        bool register_block = false;
        int err;
 
-       block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower,
+       block_cb = flow_block_cb_lookup(f->block,
+                                       mlxsw_sp_setup_tc_block_cb_flower,
                                        mlxsw_sp);
        if (!block_cb) {
                acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net);
                if (!acl_block)
                        return -ENOMEM;
-               block_cb = flow_block_cb_alloc(f->net,
-                                              mlxsw_sp_setup_tc_block_cb_flower,
+               block_cb = flow_block_cb_alloc(mlxsw_sp_setup_tc_block_cb_flower,
                                               mlxsw_sp, acl_block,
                                               mlxsw_sp_tc_block_flower_release);
                if (IS_ERR(block_cb)) {
@@ -1657,7 +1657,8 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
        struct flow_block_cb *block_cb;
        int err;
 
-       block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower,
+       block_cb = flow_block_cb_lookup(f->block,
+                                       mlxsw_sp_setup_tc_block_cb_flower,
                                        mlxsw_sp);
        if (!block_cb)
                return;
@@ -1680,7 +1681,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
                                   struct flow_block_offload *f)
 {
        struct flow_block_cb *block_cb;
-       tc_setup_cb_t *cb;
+       flow_setup_cb_t *cb;
        bool ingress;
        int err;
 
@@ -1702,7 +1703,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
                                          &mlxsw_sp_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, mlxsw_sp_port,
+               block_cb = flow_block_cb_alloc(cb, mlxsw_sp_port,
                                               mlxsw_sp_port, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
@@ -1718,7 +1719,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
        case FLOW_BLOCK_UNBIND:
                mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
                                                      f, ingress);
-               block_cb = flow_block_cb_lookup(f, cb, mlxsw_sp_port);
+               block_cb = flow_block_cb_lookup(f->block, cb, mlxsw_sp_port);
                if (!block_cb)
                        return -ENOENT;
 
@@ -6329,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:
index 131f62c..6664119 100644 (file)
@@ -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
index 1537f70..888ba43 100644 (file)
@@ -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 */
index 1df164a..17f334b 100644 (file)
@@ -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--;
 }
index 0035640..12f664f 100644 (file)
@@ -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 {
index 93ccd9f..05517c7 100644 (file)
@@ -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 = {
index bd9c2bc..63b07ed 100644 (file)
@@ -979,6 +979,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 +989,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);
 }
index b71e4ec..6932e61 100644 (file)
@@ -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();
index 7aaddc0..59487d4 100644 (file)
@@ -316,15 +316,14 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
        if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
                return -EOPNOTSUPP;
 
-       block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
-                                       port);
+       block_cb = flow_block_cb_lookup(f->block,
+                                       ocelot_setup_tc_block_cb_flower, port);
        if (!block_cb) {
                port_block = ocelot_port_block_create(port);
                if (!port_block)
                        return -ENOMEM;
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              ocelot_setup_tc_block_cb_flower,
+               block_cb = flow_block_cb_alloc(ocelot_setup_tc_block_cb_flower,
                                               port, port_block,
                                               ocelot_tc_block_unbind);
                if (IS_ERR(block_cb)) {
@@ -351,8 +350,8 @@ void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
 {
        struct flow_block_cb *block_cb;
 
-       block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
-                                       port);
+       block_cb = flow_block_cb_lookup(f->block,
+                                       ocelot_setup_tc_block_cb_flower, port);
        if (!block_cb)
                return;
 
index 9e6464f..16a6db7 100644 (file)
@@ -134,7 +134,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
                                 struct flow_block_offload *f)
 {
        struct flow_block_cb *block_cb;
-       tc_setup_cb_t *cb;
+       flow_setup_cb_t *cb;
        int err;
 
        netdev_dbg(port->dev, "tc_block command %d, binder_type %d\n",
@@ -156,7 +156,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
                if (flow_block_cb_is_busy(cb, port, &ocelot_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, port, port, NULL);
+               block_cb = flow_block_cb_alloc(cb, port, port, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
 
@@ -169,7 +169,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
                list_add_tail(&block_cb->driver_list, f->driver_block_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, cb, port);
+               block_cb = flow_block_cb_lookup(f->block, cb, port);
                if (!block_cb)
                        return -ENOENT;
 
index faa8ba0..e209f15 100644 (file)
@@ -1318,8 +1318,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
                                          &nfp_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              nfp_flower_setup_tc_block_cb,
+               block_cb = flow_block_cb_alloc(nfp_flower_setup_tc_block_cb,
                                               repr, repr, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
@@ -1328,7 +1327,8 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
                list_add_tail(&block_cb->driver_list, &nfp_block_cb_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, nfp_flower_setup_tc_block_cb,
+               block_cb = flow_block_cb_lookup(f->block,
+                                               nfp_flower_setup_tc_block_cb,
                                                repr);
                if (!block_cb)
                        return -ENOENT;
@@ -1424,8 +1424,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
                cb_priv->app = app;
                list_add(&cb_priv->list, &priv->indr_block_cb_priv);
 
-               block_cb = flow_block_cb_alloc(f->net,
-                                              nfp_flower_setup_indr_block_cb,
+               block_cb = flow_block_cb_alloc(nfp_flower_setup_indr_block_cb,
                                               cb_priv, cb_priv,
                                               nfp_flower_setup_indr_tc_release);
                if (IS_ERR(block_cb)) {
@@ -1442,7 +1441,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
                if (!cb_priv)
                        return -ENOENT;
 
-               block_cb = flow_block_cb_lookup(f,
+               block_cb = flow_block_cb_lookup(f->block,
                                                nfp_flower_setup_indr_block_cb,
                                                cb_priv);
                if (!block_cb)
index d9cbe84..1b840ee 100644 (file)
@@ -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");
 
index 70b1a03..0122919 100644 (file)
@@ -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.
 
index 8161e30..ead3750 100644 (file)
@@ -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
index 1553c9c..cf054b7 100644 (file)
@@ -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
index 4e8118a..9f51136 100644 (file)
@@ -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
index f900fde..158ac07 100644 (file)
@@ -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);
 
@@ -530,9 +530,8 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn,
        SET_FIELD(dev->dev_caps, QED_RDMA_DEV_CAP_LOCAL_INV_FENCE, 1);
 
        /* Check atomic operations support in PCI configuration space. */
-       pci_read_config_dword(cdev->pdev,
-                             cdev->pdev->pcie_cap + PCI_EXP_DEVCTL2,
-                             &pci_status_control);
+       pcie_capability_read_dword(cdev->pdev, PCI_EXP_DEVCTL2,
+                                  &pci_status_control);
 
        if (pci_status_control & PCI_EXP_DEVCTL2_LTR_EN)
                SET_FIELD(dev->dev_caps, QED_RDMA_DEV_CAP_ATOMIC_OP, 1);
index 6018992..21d3816 100644 (file)
@@ -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++;
 }
index 0637c67..e1dd6ea 100644 (file)
@@ -3251,9 +3251,9 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
 
        ret = phy_read_paged(tp->phydev, 0x0a46, 0x13);
        if (ret & BIT(8))
-               phy_modify_paged(tp->phydev, 0x0c41, 0x12, 0, BIT(1));
+               phy_modify_paged(tp->phydev, 0x0c41, 0x15, 0, BIT(1));
        else
-               phy_modify_paged(tp->phydev, 0x0c41, 0x12, BIT(1), 0);
+               phy_modify_paged(tp->phydev, 0x0c41, 0x15, BIT(1), 0);
 
        /* Enable PHY auto speed down */
        phy_modify_paged(tp->phydev, 0x0a44, 0x11, 0, BIT(3) | BIT(2));
@@ -6136,10 +6136,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 +6586,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);
index 079f459..2c5d3f5 100644 (file)
@@ -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);
                        }
                }
index 0279380..e92a178 100644 (file)
@@ -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.
 
index bd14803..8d88e40 100644 (file)
@@ -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);
index 01c2e2d..fc9954e 100644 (file)
@@ -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);
 
index 7f86dff..3174b70 100644 (file)
 #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)
 #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)
index 0a32c96..85c68b7 100644 (file)
@@ -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);
index c7c9e5f..fd54c7c 100644 (file)
@@ -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);
                }
        }
 
index 73fc252..154daf4 100644 (file)
@@ -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
index 58ea18a..37c0bc6 100644 (file)
@@ -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;
        }
 
index 5b196eb..0f34676 100644 (file)
@@ -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:
index 2f354ba..cd0a8f4 100644 (file)
@@ -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
index daab2c0..9303aeb 100644 (file)
@@ -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);
index afdcc56..3544e19 100644 (file)
@@ -836,7 +836,6 @@ int netvsc_recv_callback(struct net_device *net,
 
        if (unlikely(!skb)) {
                ++net_device_ctx->eth_stats.rx_no_memory;
-               rcu_read_unlock();
                return NVSP_STAT_FAIL;
        }
 
index 3ffe46d..7c5265f 100644 (file)
@@ -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;
        }
 
index 28676af..645d354 100644 (file)
@@ -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;
 
index 6b5cb87..7ddd91d 100644 (file)
@@ -1774,6 +1774,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);
index b86a4b2..59a94e0 100644 (file)
@@ -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;
        }
index 5d0af04..a45c5de 100644 (file)
@@ -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 {
@@ -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);
index 2d816aa..e36c04c 100644 (file)
@@ -517,7 +517,7 @@ static int sfp_hwmon_read_sensor(struct sfp *sfp, int reg, long *value)
 
 static void sfp_hwmon_to_rx_power(long *value)
 {
-       *value = DIV_ROUND_CLOSEST(*value, 100);
+       *value = DIV_ROUND_CLOSEST(*value, 10);
 }
 
 static void sfp_hwmon_calibrate(struct sfp *sfp, unsigned int slope, int offset,
index 1d902ec..a44dd3c 100644 (file)
@@ -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 = {
index 5ef422a..08364f1 100644 (file)
@@ -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)
 {
index a8e52c8..734de7d 100644 (file)
@@ -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 = {
index 3d44359..db16d7a 100644 (file)
@@ -1599,7 +1599,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 +1610,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 +1688,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 +1726,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);
index 6d25dea..f7d117d 100644 (file)
@@ -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;
 
index 69e0a2a..b6dc5d7 100644 (file)
@@ -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 */
index 39e0768..0cc03a9 100644 (file)
@@ -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
 #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 */
@@ -3191,9 +3191,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 +3577,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;
index 54edf89..6e84328 100644 (file)
@@ -165,23 +165,29 @@ static int vrf_ip6_local_out(struct net *net, struct sock *sk,
 static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb,
                                           struct net_device *dev)
 {
-       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       const struct ipv6hdr *iph;
        struct net *net = dev_net(skb->dev);
-       struct flowi6 fl6 = {
-               /* needed to match OIF rule */
-               .flowi6_oif = dev->ifindex,
-               .flowi6_iif = LOOPBACK_IFINDEX,
-               .daddr = iph->daddr,
-               .saddr = iph->saddr,
-               .flowlabel = ip6_flowinfo(iph),
-               .flowi6_mark = skb->mark,
-               .flowi6_proto = iph->nexthdr,
-               .flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF,
-       };
+       struct flowi6 fl6;
        int ret = NET_XMIT_DROP;
        struct dst_entry *dst;
        struct dst_entry *dst_null = &net->ipv6.ip6_null_entry->dst;
 
+       if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct ipv6hdr)))
+               goto err;
+
+       iph = ipv6_hdr(skb);
+
+       memset(&fl6, 0, sizeof(fl6));
+       /* needed to match OIF rule */
+       fl6.flowi6_oif = dev->ifindex;
+       fl6.flowi6_iif = LOOPBACK_IFINDEX;
+       fl6.daddr = iph->daddr;
+       fl6.saddr = iph->saddr;
+       fl6.flowlabel = ip6_flowinfo(iph);
+       fl6.flowi6_mark = skb->mark;
+       fl6.flowi6_proto = iph->nexthdr;
+       fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
+
        dst = ip6_route_output(net, NULL, &fl6);
        if (dst == dst_null)
                goto err;
@@ -237,21 +243,27 @@ static int vrf_ip_local_out(struct net *net, struct sock *sk,
 static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
                                           struct net_device *vrf_dev)
 {
-       struct iphdr *ip4h = ip_hdr(skb);
+       struct iphdr *ip4h;
        int ret = NET_XMIT_DROP;
-       struct flowi4 fl4 = {
-               /* needed to match OIF rule */
-               .flowi4_oif = vrf_dev->ifindex,
-               .flowi4_iif = LOOPBACK_IFINDEX,
-               .flowi4_tos = RT_TOS(ip4h->tos),
-               .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF,
-               .flowi4_proto = ip4h->protocol,
-               .daddr = ip4h->daddr,
-               .saddr = ip4h->saddr,
-       };
+       struct flowi4 fl4;
        struct net *net = dev_net(vrf_dev);
        struct rtable *rt;
 
+       if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct iphdr)))
+               goto err;
+
+       ip4h = ip_hdr(skb);
+
+       memset(&fl4, 0, sizeof(fl4));
+       /* needed to match OIF rule */
+       fl4.flowi4_oif = vrf_dev->ifindex;
+       fl4.flowi4_iif = LOOPBACK_IFINDEX;
+       fl4.flowi4_tos = RT_TOS(ip4h->tos);
+       fl4.flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF;
+       fl4.flowi4_proto = ip4h->protocol;
+       fl4.daddr = ip4h->daddr;
+       fl4.saddr = ip4h->saddr;
+
        rt = ip_route_output_flow(net, &fl4, NULL);
        if (IS_ERR(rt))
                goto err;
index a9ac3f3..e2e679a 100644 (file)
@@ -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",
index d436cc5..2fb4258 100644 (file)
@@ -177,6 +177,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_get_cfg
        },
        {
@@ -184,6 +185,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_set_cfg
        },
        {
@@ -192,6 +194,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_get_selected
        },
        {
@@ -200,6 +203,7 @@ static const struct wiphy_vendor_command wil_nl80211_vendor_commands[] = {
                        QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR,
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
+               .policy = wil_rf_sector_policy,
                .doit = wil_rf_sector_set_selected
        },
 };
index f650089..d07e7c7 100644 (file)
@@ -112,6 +112,7 @@ const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
                         WIPHY_VENDOR_CMD_NEED_NETDEV,
+               .policy = VENDOR_CMD_RAW_DATA,
                .doit = brcmf_cfg80211_vndr_cmds_dcmd_handler
        },
 };
index d55312e..9b0bb89 100644 (file)
@@ -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,
 };
 
 /**
index e411ac9..4d81776 100644 (file)
@@ -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);
index 57d0904..38672dd 100644 (file)
@@ -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);
index 1d608e9..5de54d1 100644 (file)
@@ -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);
index 55cd49c..1c904b5 100644 (file)
@@ -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;
        }
@@ -3494,11 +3506,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 +3565,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 +3710,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 +5066,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 +5076,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),
index 48c77af..a263cc6 100644 (file)
@@ -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,
index 719f793..a9bb43a 100644 (file)
@@ -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);
 
index d7d6f33..4888054 100644 (file)
@@ -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);
 }
index 8c9069f..d3f04ac 100644 (file)
@@ -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);
 }
 
 /**
index f7eb60d..428642e 100644 (file)
@@ -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;
 };
 
index 64f9505..854edd7 100644 (file)
@@ -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);
 }
index f545a73..10f1853 100644 (file)
@@ -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,
index 4487cc3..8d70093 100644 (file)
@@ -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;
 
 /**
index a3e5d88..6ac114a 100644 (file)
@@ -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)
index 9ecd5f0..b8e20a0 100644 (file)
@@ -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, },
        };
 
index ea2a03d..de711c1 100644 (file)
@@ -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)},
index fa4245d..2f0ba7e 100644 (file)
@@ -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;
 
index 519b4ee..772e54f 100644 (file)
@@ -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:
index 3e442c7..095837f 100644 (file)
@@ -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
index 0d6d417..21dda38 100644 (file)
@@ -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)
index 5cf0b32..e1bd344 100644 (file)
@@ -163,6 +163,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
                .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
                .doit = wlcore_vendor_cmd_smart_config_start,
+               .policy = wlcore_vendor_attr_policy,
        },
        {
                .info = {
@@ -172,6 +173,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
                .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
                .doit = wlcore_vendor_cmd_smart_config_stop,
+               .policy = wlcore_vendor_attr_policy,
        },
        {
                .info = {
@@ -181,6 +183,7 @@ static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
                .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
                         WIPHY_VENDOR_CMD_NEED_RUNNING,
                .doit = wlcore_vendor_cmd_smart_config_set_group_key,
+               .policy = wlcore_vendor_attr_policy,
        },
 };
 
index e65d027..529be35 100644 (file)
@@ -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);
 }
 
index 9a22056..e5a622c 100644 (file)
@@ -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.");
index 945cc90..888e298 100644 (file)
@@ -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);
 
index c3e10b6..f25f1ec 100644 (file)
@@ -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);
index 06fc542..6586378 100644 (file)
@@ -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],
index 9dddf13..0a5e884 100644 (file)
@@ -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;
index 62d00ff..3508a79 100644 (file)
@@ -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;
 }
index 2dca303..798c5c4 100644 (file)
@@ -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,
 };
 
index 5e1f060..9204f1e 100644 (file)
@@ -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;
 }
index dfecd6e..29a065e 100644 (file)
@@ -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;
 }
index 2d8d7e5..a16e522 100644 (file)
@@ -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));
index 391e88d..0ac52b6 100644 (file)
@@ -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__ */
index df2bdbd..3e7b11c 100644 (file)
@@ -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;
 }
index 2bf3acd..4c121dd 100644 (file)
@@ -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;
index ef46cc3..37bf871 100644 (file)
@@ -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);
index 56f2227..af30cbe 100644 (file)
@@ -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;
 }
index cc09b81..8f3fbe5 100644 (file)
@@ -2311,17 +2311,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 +2475,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)) {
index a9a9276..4f0d0d1 100644 (file)
@@ -12,11 +12,6 @@ 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)
-{
-       return multipath && ctrl->subsys && (ctrl->subsys->cmic & (1 << 3));
-}
-
 /*
  * If multipathing is enabled we need to always use the subsystem instance
  * number for numbering our devices to avoid conflicts between subsystems that
@@ -622,7 +617,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;
index 716a876..26b563f 100644 (file)
@@ -485,7 +485,11 @@ 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_set_disk_name(char *disk_name, struct nvme_ns *ns,
                        struct nvme_ctrl *ctrl, int *flags);
 void nvme_failover_req(struct request *req);
index bb970ca..db160ce 100644 (file)
@@ -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;
@@ -3029,6 +3027,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) },
index 6f303b9..9e0c429 100644 (file)
@@ -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
index 29ed5ec..1b27b5a 100644 (file)
@@ -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;
index 1be03a9..d22d1b8 100644 (file)
@@ -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);
index 308c3e0..1b33012 100644 (file)
@@ -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 */
index eb6168e..590e594 100644 (file)
@@ -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:
index 2d06b80..df352b3 100644 (file)
@@ -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:
index 384396c..2225657 100644 (file)
@@ -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)
 {
index 053101f..ba6438a 100644 (file)
@@ -2507,6 +2507,61 @@ 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
+                       map = ERR_PTR(-ENODEV);
+
+               ctx->maps[ASPEED_IP_LPC] = map;
+               dev_dbg(ctx->dev, "Acquired LPC regmap");
+               return map;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+
 /**
  * Configure a pin's signal by applying an expression's descriptor state for
  * all descriptors in the expression.
@@ -2520,7 +2575,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 +2586,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
@@ -2641,34 +2702,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);
index 535db3d..5493366 100644 (file)
@@ -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;
 
index 5b0fe17..839c01b 100644 (file)
@@ -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",
index 329d54d..52d299b 100644 (file)
@@ -702,11 +702,12 @@ struct aspeed_pin_function {
 struct aspeed_pinmux_data;
 
 struct aspeed_pinmux_ops {
-       int (*set)(const struct aspeed_pinmux_data *ctx,
+       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;
@@ -725,7 +726,7 @@ int aspeed_sig_expr_eval(const 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)
 {
index 48d6f0d..83ed1fb 100644 (file)
@@ -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",
index 235c0b8..c510d0d 100644 (file)
@@ -812,6 +812,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = {
        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(ICELAKE_NNPI, icl_reg_map),
        {}
 };
 
index b0d3110..e4c68ef 100644 (file)
@@ -93,7 +93,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 +255,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");
index 9fd6dd3..6df4818 100644 (file)
@@ -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");
index 540e8aa..f808c5f 100644 (file)
@@ -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>");
index c3ab07a..8edfac1 100644 (file)
@@ -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
index 1520533..989506b 100644 (file)
 #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
 #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),
 };
 
index 5d067f7..0c440c5 100644 (file)
@@ -163,7 +163,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 +182,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++) {
index 397918e..9112faa 100644 (file)
@@ -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);
index b9ce93e..99f8661 100644 (file)
@@ -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);
index 8c9d412..e7cf0a1 100644 (file)
@@ -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)
index 8d3370d..3e0b2f6 100644 (file)
@@ -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;
index 730c4e6..4142c85 100644 (file)
@@ -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 */
index 8c1d235..7a838e3 100644 (file)
@@ -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,
index 1d4c893..3645d17 100644 (file)
@@ -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;
 }
 
index 2b90a5e..9208c0e 100644 (file)
@@ -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);
index 5ea83dc..dad2be3 100644 (file)
@@ -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;
index 12fe9de..a36251d 100644 (file)
@@ -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",
index 1b4ee57..4a8a537 100644 (file)
@@ -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:
index e02f295..1534420 100644 (file)
@@ -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;
index fd64bc3..cbead3d 100644 (file)
@@ -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");
index 1a55e59..957889a 100644 (file)
@@ -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);
index 75f66f8..1b92f3c 100644 (file)
@@ -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
index aea4fd7..6c68c23 100644 (file)
@@ -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;
index f0066f8..4971104 100644 (file)
@@ -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,
index 590ec80..1791a39 100644 (file)
@@ -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:
index 43a6b53..1bb6aad 100644 (file)
@@ -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
@@ -5653,6 +5657,12 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
        if (c == NULL)
                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);
index acd16e0..8cdbac0 100644 (file)
@@ -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);
index e0f3852..da6e97d 100644 (file)
@@ -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;
 
index b2339d0..f9f0793 100644 (file)
@@ -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;
        }
 
index a32b3f0..120e3c4 100644 (file)
@@ -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;
index 6846628..050c0f0 100644 (file)
@@ -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));
index 4059655..da83034 100644 (file)
@@ -4877,7 +4877,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);
index 9381171..11e64b5 100644 (file)
@@ -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);
index 62c6ba1..c9519e6 100644 (file)
@@ -419,7 +419,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
index 6f243a9..840b1b8 100644 (file)
@@ -834,7 +834,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 &&
+           tfr->rx_buf != ctlr->dummy_rx)
                cs |= BCM2835_SPI_CS_REN;
        else
                cs &= ~BCM2835_SPI_CS_REN;
index 41a49b9..448c00e 100644 (file)
@@ -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,
index eca9d52..9eb8215 100644 (file)
@@ -410,6 +410,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;
 
index fc7ab4b..bb6a14d 100644 (file)
@@ -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:
index fd4995f..f85ec5b 100644 (file)
@@ -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);
 }
 
index b6c6d66..e2c7646 100644 (file)
@@ -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);
index d609a2b..fd32376 100644 (file)
@@ -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 */
index b090e7a..85e54a1 100644 (file)
@@ -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;
index b3d0701..5a129b1 100644 (file)
@@ -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 */
index bbf75f7..88a5b69 100644 (file)
@@ -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);
index 4cfe9f8..37622c9 100644 (file)
@@ -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);
 }
index 564a38e..c77832a 100644 (file)
@@ -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 */
index 2ea814d..63c65dd 100644 (file)
@@ -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 */
index 7cbc1bd..cf5700a 100644 (file)
@@ -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;
index 2be45ee..464648e 100644 (file)
@@ -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:
index 9d4f1da..40dd573 100644 (file)
@@ -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.
index d72fdd3..736eede 100644 (file)
@@ -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);
 
index 22dd4c4..c70caf4 100644 (file)
@@ -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;
 
index 343b129..e877b91 100644 (file)
@@ -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;
index 213ab3c..d3446ac 100644 (file)
@@ -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);
 }
index cb4db1b..5fb214e 100644 (file)
@@ -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>
index fd385c8..3083dba 100644 (file)
@@ -1035,25 +1035,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
index 7cd7cab..15a0fcc 100644 (file)
@@ -59,7 +59,6 @@ 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
index bfe5e9e..c7d51b5 100644 (file)
@@ -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/netx-serial.c b/drivers/tty/serial/netx-serial.c
deleted file mode 100644 (file)
index b355686..0000000
+++ /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);
index 717292c..60ff236 100644 (file)
@@ -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;
index ec92f36..34aa39d 100644 (file)
@@ -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);
 }
index b265ab5..9063ede 100644 (file)
@@ -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)
index 8853393..2ccbc2f 100644 (file)
@@ -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,
-};
-
-
-
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -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.
index 7e88fdf..f19694e 100644 (file)
@@ -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);
index bd8d01f..0c9fde5 100644 (file)
@@ -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)
index fe9422d..b0882c1 100644 (file)
@@ -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;
 
                /*
index 09a8ebd..6968b9f 100644 (file)
@@ -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;
 
index a033f7d..f4e13a3 100644 (file)
@@ -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 */
index 3ce71cb..f6d0449 100644 (file)
@@ -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);
 
index 63c6330..e729de2 100644 (file)
@@ -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);
index c2fe218..1e0236e 100644 (file)
@@ -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 &&
index 671bce1..8616c52 100644 (file)
@@ -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;
index 248cd7a..03d1e55 100644 (file)
@@ -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) {
index 7a26496..f5c4144 100644 (file)
@@ -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;
index ba05dd8..f5bed9f 100644 (file)
@@ -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 ,
index 27e9c78..a32d61a 100644 (file)
@@ -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);
 }
index 4d6ae37..6ca9111 100644 (file)
@@ -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.
index 7b306aa..6715a12 100644 (file)
@@ -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);
 }
 
index 3079024..05b8021 100644 (file)
@@ -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,
@@ -128,6 +131,14 @@ static int slave_configure(struct scsi_device *sdev)
                blk_queue_max_hw_sectors(sdev->request_queue, 2048);
        }
 
+       /*
+        * 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
index fba32d8..15abe1d 100644 (file)
@@ -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;
 }
@@ -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;
 }
index f7a79a2..8e9f8fb 100644 (file)
@@ -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);
index 8192963..42a8c2a 100644 (file)
@@ -96,7 +96,7 @@ struct vhost_uaddr {
 };
 
 #if defined(CONFIG_MMU_NOTIFIER) && ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE == 0
-#define VHOST_ARCH_CAN_ACCEL_UACCESS 1
+#define VHOST_ARCH_CAN_ACCEL_UACCESS 0
 #else
 #define VHOST_ARCH_CAN_ACCEL_UACCESS 0
 #endif
index 90eca64..702cca5 100644 (file)
@@ -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);
index b9b2d06..668a1c7 100644 (file)
@@ -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))
index 1b2cf5b..c3c93e0 100644 (file)
@@ -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);
index 41a2a11..b35f7be 100644 (file)
@@ -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);
index 5a6ced7..202fc8d 100644 (file)
@@ -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:
                /*
index efd7996..4626830 100644 (file)
@@ -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;
index 0650100..7d278b3 100644 (file)
@@ -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:
index 567005d..5c52c73 100644 (file)
@@ -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);
index 4c339c7..a446a72 100644 (file)
@@ -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 {
index 2f5ce72..c6070e7 100644 (file)
@@ -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) ?
index cfbe467..ae1df49 100644 (file)
@@ -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);
index 73427d8..e569413 100644 (file)
@@ -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;
index ba883a8..7b1077f 100644 (file)
@@ -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);
index 1ce73e0..114f281 100644 (file)
@@ -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:
index 18722aa..2575503 100644 (file)
@@ -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;
index 4707dff..eb657ab 100644 (file)
@@ -345,15 +345,24 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        struct bio *bio;
        bool is_poll = (iocb->ki_flags & IOCB_HIPRI) != 0;
        bool is_read = (iov_iter_rw(iter) == READ), is_sync;
+       bool nowait = (iocb->ki_flags & IOCB_NOWAIT) != 0;
        loff_t pos = iocb->ki_pos;
        blk_qc_t qc = BLK_QC_T_NONE;
-       int ret = 0;
+       gfp_t gfp;
+       int ret;
 
        if ((pos | iov_iter_alignment(iter)) &
            (bdev_logical_block_size(bdev) - 1))
                return -EINVAL;
 
-       bio = bio_alloc_bioset(GFP_KERNEL, nr_pages, &blkdev_dio_pool);
+       if (nowait)
+               gfp = GFP_NOWAIT;
+       else
+               gfp = GFP_KERNEL;
+
+       bio = bio_alloc_bioset(gfp, nr_pages, &blkdev_dio_pool);
+       if (!bio)
+               return -EAGAIN;
 
        dio = container_of(bio, struct blkdev_dio, bio);
        dio->is_sync = is_sync = is_sync_kiocb(iocb);
@@ -375,6 +384,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        if (!is_poll)
                blk_start_plug(&plug);
 
+       ret = 0;
        for (;;) {
                bio_set_dev(bio, bdev);
                bio->bi_iter.bi_sector = pos >> 9;
@@ -399,7 +409,14 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                        task_io_account_write(bio->bi_iter.bi_size);
                }
 
-               dio->size += bio->bi_iter.bi_size;
+               /*
+                * Tell underlying layer to not block for resource shortage.
+                * And if we would have blocked, return error inline instead
+                * of through the bio->bi_end_io() callback.
+                */
+               if (nowait)
+                       bio->bi_opf |= (REQ_NOWAIT | REQ_NOWAIT_INLINE);
+
                pos += bio->bi_iter.bi_size;
 
                nr_pages = iov_iter_npages(iter, BIO_MAX_PAGES);
@@ -411,7 +428,13 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                                polled = true;
                        }
 
+                       dio->size += bio->bi_iter.bi_size;
                        qc = submit_bio(bio);
+                       if (qc == BLK_QC_T_EAGAIN) {
+                               dio->size -= bio->bi_iter.bi_size;
+                               ret = -EAGAIN;
+                               goto error;
+                       }
 
                        if (polled)
                                WRITE_ONCE(iocb->ki_cookie, qc);
@@ -432,8 +455,19 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                        atomic_inc(&dio->ref);
                }
 
-               submit_bio(bio);
-               bio = bio_alloc(GFP_KERNEL, nr_pages);
+               dio->size += bio->bi_iter.bi_size;
+               qc = submit_bio(bio);
+               if (qc == BLK_QC_T_EAGAIN) {
+                       dio->size -= bio->bi_iter.bi_size;
+                       ret = -EAGAIN;
+                       goto error;
+               }
+
+               bio = bio_alloc(gfp, nr_pages);
+               if (!bio) {
+                       ret = -EAGAIN;
+                       goto error;
+               }
        }
 
        if (!is_poll)
@@ -453,6 +487,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        }
        __set_current_state(TASK_RUNNING);
 
+out:
        if (!ret)
                ret = blk_status_to_errno(dio->bio.bi_status);
        if (likely(!ret))
@@ -460,6 +495,10 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
 
        bio_put(&dio->bio);
        return ret;
+error:
+       if (!is_poll)
+               blk_finish_plug(&plug);
+       goto out;
 }
 
 static ssize_t
@@ -1139,8 +1178,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 +1225,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 +1750,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
index 212b4a8..38651fa 100644 (file)
@@ -4,6 +4,7 @@ config BTRFS_FS
        tristate "Btrfs filesystem support"
        select CRYPTO
        select CRYPTO_CRC32C
+       select LIBCRC32C
        select ZLIB_INFLATE
        select ZLIB_DEFLATE
        select LZO_COMPRESS
index 89116af..e5d8531 100644 (file)
@@ -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);
index 41a2bd2..5f7ee70 100644 (file)
@@ -4106,6 +4106,7 @@ void close_ctree(struct btrfs_fs_info *fs_info)
        percpu_counter_destroy(&fs_info->dev_replace.bio_counter);
        cleanup_srcu_struct(&fs_info->subvol_srcu);
 
+       btrfs_free_csum_hash(fs_info);
        btrfs_free_stripe_hash_table(fs_info);
        btrfs_free_ref_cache(fs_info);
 }
index 1af069a..ee582a3 100644 (file)
@@ -395,10 +395,31 @@ static noinline int add_async_extent(struct async_chunk *cow,
        return 0;
 }
 
+/*
+ * Check if the inode has flags compatible with compression
+ */
+static inline bool inode_can_compress(struct inode *inode)
+{
+       if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW ||
+           BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)
+               return false;
+       return true;
+}
+
+/*
+ * Check if the inode needs to be submitted to compression, based on mount
+ * options, defragmentation, properties or heuristics.
+ */
 static inline int inode_need_compress(struct inode *inode, u64 start, u64 end)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 
+       if (!inode_can_compress(inode)) {
+               WARN(IS_ENABLED(CONFIG_BTRFS_DEBUG),
+                       KERN_ERR "BTRFS: unexpected compression for ino %llu\n",
+                       btrfs_ino(BTRFS_I(inode)));
+               return 0;
+       }
        /* force compress */
        if (btrfs_test_opt(fs_info, FORCE_COMPRESS))
                return 1;
@@ -1631,7 +1652,8 @@ int btrfs_run_delalloc_range(struct inode *inode, struct page *locked_page,
        } else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC && !force_cow) {
                ret = run_delalloc_nocow(inode, locked_page, start, end,
                                         page_started, 0, nr_written);
-       } else if (!inode_need_compress(inode, start, end)) {
+       } else if (!inode_can_compress(inode) ||
+                  !inode_need_compress(inode, start, end)) {
                ret = cow_file_range(inode, locked_page, start, end, end,
                                      page_started, nr_written, 1, NULL);
        } else {
index 98fccce..393eced 100644 (file)
@@ -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);
index 1744ba8..ae7f64a 100644 (file)
@@ -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);
        }
index 69b59bf..c3c0c06 100644 (file)
@@ -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)
index 3b8ae1a..e3adb71 100644 (file)
@@ -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);
@@ -659,6 +663,16 @@ struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root
                                 BTRFS_RESERVE_NO_FLUSH, true);
 }
 
+/*
+ * 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
  *
@@ -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);
index 527ea94..2c5a6f6 100644 (file)
@@ -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);
index a13ddba..d74b74c 100644 (file)
@@ -5941,6 +5941,7 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        u64 stripe_len;
        u64 raid56_full_stripe_start = (u64)-1;
        int data_stripes;
+       int ret = 0;
 
        ASSERT(op != BTRFS_MAP_DISCARD);
 
@@ -5961,8 +5962,8 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                btrfs_crit(fs_info,
 "stripe math has gone wrong, stripe_offset=%llu offset=%llu start=%llu logical=%llu stripe_len=%llu",
                        stripe_offset, offset, em->start, logical, stripe_len);
-               free_extent_map(em);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        /* stripe_offset is the offset of this block in its stripe */
@@ -6009,7 +6010,10 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        io_geom->stripe_offset = stripe_offset;
        io_geom->raid56_stripe_offset = raid56_full_stripe_start;
 
-       return 0;
+out:
+       /* once for us */
+       free_extent_map(em);
+       return ret;
 }
 
 static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
index a4830ce..a15a6e7 100644 (file)
@@ -1113,6 +1113,7 @@ cifs_demultiplex_thread(void *p)
                mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
 
        set_freezable();
+       allow_signal(SIGKILL);
        while (server->tcpStatus != CifsExiting) {
                if (try_to_freeze())
                        continue;
index a5bc1b6..64a5864 100644 (file)
@@ -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;
index c8cd7b6..31e4a1b 100644 (file)
@@ -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;
index 6e30949..a7ec2d3 100644 (file)
@@ -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 */
index e42e17e..b1ea7df 100644 (file)
@@ -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);
index a237141..6bf81f9 100644 (file)
--- 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) {
index c71cbfe..f7f6a14 100644 (file)
--- 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)
index f8d46df..3e58a6f 100644 (file)
@@ -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)
index 6691f52..8974672 100644 (file)
@@ -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:
index 6de6cda..78a1b87 100644 (file)
@@ -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;
                }
index 79581b9..4f8b5fd 100644 (file)
@@ -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;
 }
index e2a66e1..d542f1c 100644 (file)
@@ -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);
        }
@@ -1064,8 +1066,44 @@ 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 -= (seg_skip << PAGE_SHIFT);
+                       iter->iov_offset = offset & ~PAGE_MASK;
+                       if (iter->iov_offset)
+                               iter->count -= iter->iov_offset;
+               }
+       }
+
        return 0;
 }
 
@@ -1120,28 +1158,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 +1666,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 +1838,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 +1883,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 +1934,7 @@ restart:
                }
        }
 
+out:
        if (cur_mm) {
                set_fs(old_fs);
                unuse_mm(cur_mm);
@@ -1917,6 +1961,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;
index 2d16538..93cd119 100644 (file)
@@ -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.
index 6464ea4..d28d30b 100644 (file)
@@ -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);
        }
 }
 
index 0ff3fac..071b90a 100644 (file)
@@ -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);
index 5799777..9eb87ae 100644 (file)
@@ -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);
index 53507aa..3800ab6 100644 (file)
@@ -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));
index 25a75e4..ad041cf 100644 (file)
@@ -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 ";
 }
index d778dad..3564da1 100644 (file)
@@ -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);
index 616393a..da62040 100644 (file)
@@ -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);
 }
 
 /*
index 39896af..1406858 100644 (file)
@@ -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;
index 9afd051..cad4e06 100644 (file)
@@ -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);
index 75bd5b5..4525d5a 100644 (file)
@@ -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);
index 628631e..703f595 100644 (file)
@@ -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,
index 385f3aa..90c830e 100644 (file)
@@ -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;
 
index b5b8046..a59abe3 100644 (file)
--- 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);
index 113c58f..5960578 100644 (file)
@@ -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);
 }
 
 /**
index 94c4f1d..77ff9f9 100644 (file)
@@ -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;
 }
index a8a06bb..f5c955d 100644 (file)
@@ -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;
index 8666fe7..02970b1 100644 (file)
@@ -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
index c64bea7..e9f20b8 100644 (file)
@@ -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__ */
 
index 72d51d1..5cf2c5d 100644 (file)
@@ -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);
index 759d462..f57eea0 100644 (file)
@@ -852,6 +852,13 @@ struct drm_mode_config {
        /* dumb ioctl parameters */
        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:
         *
index b6b127e..8ccc29a 100644 (file)
 #define CLKID_VDEC_HEVC                                207
 #define CLKID_VDEC_HEVCF                       210
 #define CLKID_TS                               212
+#define CLKID_CPUB_CLK                         224
 
 #endif /* __G12A_CLKC_H */
index 4236818..673a8c6 100644 (file)
 #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 (file)
index 0000000..5255b1c
--- /dev/null
@@ -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/reset/mt7629-resets.h b/include/dt-bindings/reset/mt7629-resets.h
new file mode 100644 (file)
index 0000000..6bb8573
--- /dev/null
@@ -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 */
index 16c769a..6db0304 100644 (file)
@@ -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) {}
index 46bbc94..7a30524 100644 (file)
@@ -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)
index 689a582..1281109 100644 (file)
@@ -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);
index feff3fe..1b1fa15 100644 (file)
@@ -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)
index 55cb455..a5dfbaf 100644 (file)
@@ -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 */
 
index 2ae7604..dce5521 100644 (file)
@@ -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);
index 3c096c7..853a8f1 100644 (file)
@@ -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
index 6b6c739..cb73264 100644 (file)
@@ -50,7 +50,6 @@ struct cn_dev {
 
        u32 seq, groups;
        struct sock *nls;
-       void (*input) (struct sk_buff *skb);
 
        struct cn_queue_dev *cbdev;
 };
index 7eb43a0..f7a30e0 100644 (file)
@@ -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;
 }
 
index c330b75..6717ade 100644 (file)
@@ -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);
index d3a0fbf..9fa4b3f 100644 (file)
@@ -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
index e11b115..f7d1eea 100644 (file)
@@ -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
index 17cd007..1dd014c 100644 (file)
@@ -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 *);
index ff65d22..92c6e31 100644 (file)
@@ -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) &&                                 \
index 56b8e35..997a530 100644 (file)
@@ -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);
index 9ddcf50..a7f08fb 100644 (file)
@@ -247,7 +247,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 +256,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 +264,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 +317,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 +326,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 +359,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 +368,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 +382,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 +397,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 +411,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 +427,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 +441,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 +456,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 +471,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 +513,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,7 +525,7 @@ 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;
 }
 
index b8a08b2..7ef56dc 100644 (file)
@@ -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)
 {
index 8b72875..69e813b 100644 (file)
@@ -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 {
index b4f5403..9661416 100644 (file)
@@ -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>"
index 781b96a..a0637ab 100644 (file)
@@ -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)
index 5c5b586..fcb46b3 100644 (file)
@@ -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
 /*
index 04a5695..f049af3 100644 (file)
@@ -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,
index b3d5752..ec571fd 100644 (file)
@@ -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];
 };
index b2c1648..5714fd3 100644 (file)
@@ -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];
index 91d6275..19df783 100644 (file)
@@ -1,7 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /****************************************************************************
- * ip_conntrack_h323_asn1.h - BER and PER decoding library for H.323
- *                           conntrack/NAT module.
+ * BER and PER decoding library for H.323 conntrack/NAT module.
  *
  * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
index 0cf8570..844f89e 100644 (file)
@@ -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.
  *
index 1dda318..7128373 100644 (file)
@@ -32,6 +32,7 @@
 
 #endif /* CONFIG_SPARSEMEM */
 
+#ifndef BUILD_VDSO32_64
 /*
  * page->flags layout:
  *
 #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
 
 /*
 #define LAST_CPUPID_NOT_IN_PAGE_FLAGS
 #endif
 
+#endif
 #endif /* _LINUX_PAGE_FLAGS_LAYOUT */
index b848517..f91cb88 100644 (file)
@@ -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)
index 8dc1811..9f51932 100644 (file)
@@ -1092,7 +1092,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:
index e7dd04a..3988762 100644 (file)
@@ -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,
index 50ced8a..e4b3fb4 100644 (file)
@@ -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;
        }
 }
index b6f77cf..30c5155 100644 (file)
@@ -126,6 +126,19 @@ static inline int waitqueue_active(struct wait_queue_head *wq_head)
        return !list_empty(&wq_head->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
index 88c2715..26e2ad2 100644 (file)
@@ -4170,7 +4170,7 @@ struct sta_opmode_info {
        u8 rx_nss;
 };
 
-#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)ERR_PTR(-ENODATA))
+#define VENDOR_CMD_RAW_DATA ((const struct nla_policy *)(long)(-ENODATA))
 
 /**
  * struct wiphy_vendor_command - vendor command definition
@@ -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 */
index db33729..b16d216 100644 (file)
@@ -2,8 +2,8 @@
 #define _NET_FLOW_OFFLOAD_H
 
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <net/flow_dissector.h>
-#include <net/sch_generic.h>
 
 struct flow_match {
        struct flow_dissector   *dissector;
@@ -249,6 +249,10 @@ enum flow_block_binder_type {
        FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
 };
 
+struct flow_block {
+       struct list_head cb_list;
+};
+
 struct netlink_ext_ack;
 
 struct flow_block_offload {
@@ -256,29 +260,33 @@ struct flow_block_offload {
        enum flow_block_binder_type binder_type;
        bool block_shared;
        struct net *net;
+       struct flow_block *block;
        struct list_head cb_list;
        struct list_head *driver_block_list;
        struct netlink_ext_ack *extack;
 };
 
+enum tc_setup_type;
+typedef int flow_setup_cb_t(enum tc_setup_type type, void *type_data,
+                           void *cb_priv);
+
 struct flow_block_cb {
        struct list_head        driver_list;
        struct list_head        list;
-       struct net              *net;
-       tc_setup_cb_t           *cb;
+       flow_setup_cb_t         *cb;
        void                    *cb_ident;
        void                    *cb_priv;
        void                    (*release)(void *cb_priv);
        unsigned int            refcnt;
 };
 
-struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
                                          void *cb_ident, void *cb_priv,
                                          void (*release)(void *cb_priv));
 void flow_block_cb_free(struct flow_block_cb *block_cb);
 
-struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *offload,
-                                          tc_setup_cb_t *cb, void *cb_ident);
+struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
+                                          flow_setup_cb_t *cb, void *cb_ident);
 
 void *flow_block_cb_priv(struct flow_block_cb *block_cb);
 void flow_block_cb_incref(struct flow_block_cb *block_cb);
@@ -296,11 +304,12 @@ static inline void flow_block_cb_remove(struct flow_block_cb *block_cb,
        list_move(&block_cb->list, &offload->cb_list);
 }
 
-bool flow_block_cb_is_busy(tc_setup_cb_t *cb, void *cb_ident,
+bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident,
                           struct list_head *driver_block_list);
 
 int flow_block_cb_setup_simple(struct flow_block_offload *f,
-                              struct list_head *driver_list, tc_setup_cb_t *cb,
+                              struct list_head *driver_list,
+                              flow_setup_cb_t *cb,
                               void *cb_ident, void *cb_priv, bool ingress_only);
 
 enum flow_cls_command {
@@ -333,4 +342,9 @@ flow_cls_offload_flow_rule(struct flow_cls_offload *flow_cmd)
        return flow_cmd->rule;
 }
 
+static inline void flow_block_init(struct flow_block *flow_block)
+{
+       INIT_LIST_HEAD(&flow_block->cb_list);
+}
+
 #endif /* _NET_FLOW_OFFLOAD_H */
index 93ce6b0..573429b 100644 (file)
@@ -76,6 +76,11 @@ struct nf_conntrack_expect_policy {
 #define NF_CT_EXPECT_CLASS_DEFAULT     0
 #define NF_CT_EXPECT_MAX_CNT           255
 
+/* Allow to reuse expectations with the same tuples from different master
+ * conntracks.
+ */
+#define NF_CT_EXP_F_SKIP_MASTER        0x1
+
 int nf_conntrack_expect_pernet_init(struct net *net);
 void nf_conntrack_expect_pernet_fini(struct net *net);
 
@@ -122,10 +127,11 @@ void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
                       u_int8_t, const __be16 *, const __be16 *);
 void nf_ct_expect_put(struct nf_conntrack_expect *exp);
 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, 
-                               u32 portid, int report);
-static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect)
+                               u32 portid, int report, unsigned int flags);
+static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect,
+                                      unsigned int flags)
 {
-       return nf_ct_expect_related_report(expect, 0, 0);
+       return nf_ct_expect_related_report(expect, 0, 0, flags);
 }
 
 #endif /*_NF_CONNTRACK_EXPECT_H*/
index 8f00125..44513b9 100644 (file)
@@ -68,6 +68,7 @@ struct synproxy_options {
        u8                              options;
        u8                              wscale;
        u16                             mss;
+       u16                             mss_encode;
        u32                             tsval;
        u32                             tsecr;
 };
index 35dfdd9..9b62456 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/rhashtable.h>
 #include <net/netfilter/nf_flow_table.h>
 #include <net/netlink.h>
+#include <net/flow_offload.h>
 
 struct module;
 
@@ -951,7 +952,7 @@ struct nft_stats {
  *     @stats: per-cpu chain stats
  *     @chain: the chain
  *     @dev_name: device name that this base chain is attached to (if any)
- *     @cb_list: list of flow block callbacks (for hardware offload)
+ *     @flow_block: flow block (for hardware offload)
  */
 struct nft_base_chain {
        struct nf_hook_ops              ops;
@@ -961,7 +962,7 @@ struct nft_base_chain {
        struct nft_stats __percpu       *stats;
        struct nft_chain                chain;
        char                            dev_name[IFNAMSIZ];
-       struct list_head                cb_list;
+       struct flow_block               flow_block;
 };
 
 static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
index 841faad..e429809 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/workqueue.h>
 #include <net/sch_generic.h>
 #include <net/act_api.h>
-#include <net/flow_offload.h>
 #include <net/net_namespace.h>
 
 /* TC action not accessible from user space */
@@ -126,14 +125,14 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
 }
 
 static inline
-int tc_setup_cb_block_register(struct tcf_block *block, tc_setup_cb_t *cb,
+int tc_setup_cb_block_register(struct tcf_block *block, flow_setup_cb_t *cb,
                               void *cb_priv)
 {
        return 0;
 }
 
 static inline
-void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
+void tc_setup_cb_block_unregister(struct tcf_block *block, flow_setup_cb_t *cb,
                                  void *cb_priv)
 {
 }
index 855167b..6b6b012 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mutex.h>
 #include <net/gen_stats.h>
 #include <net/rtnetlink.h>
+#include <net/flow_offload.h>
 
 struct Qdisc_ops;
 struct qdisc_walker;
@@ -22,9 +23,6 @@ struct tcf_walker;
 struct module;
 struct bpf_flow_keys;
 
-typedef int tc_setup_cb_t(enum tc_setup_type type,
-                         void *type_data, void *cb_priv);
-
 typedef int tc_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv,
                                    enum tc_setup_type type, void *type_data);
 
@@ -313,7 +311,7 @@ struct tcf_proto_ops {
        void                    (*walk)(struct tcf_proto *tp,
                                        struct tcf_walker *arg, bool rtnl_held);
        int                     (*reoffload)(struct tcf_proto *tp, bool add,
-                                            tc_setup_cb_t *cb, void *cb_priv,
+                                            flow_setup_cb_t *cb, void *cb_priv,
                                             struct netlink_ext_ack *extack);
        void                    (*bind_class)(void *, u32, unsigned long);
        void *                  (*tmplt_create)(struct net *net,
@@ -401,7 +399,7 @@ struct tcf_block {
        refcount_t refcnt;
        struct net *net;
        struct Qdisc *q;
-       struct list_head cb_list;
+       struct flow_block flow_block;
        struct list_head owner_list;
        bool keep_dst;
        unsigned int offloadcnt; /* Number of oddloaded filters */
index 8b9ef36..cfdc7cb 100644 (file)
@@ -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;
 }
 
index 0a559d4..b4fce0f 100644 (file)
@@ -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 */
index f42d300..81e8ade 100644 (file)
@@ -1709,6 +1709,11 @@ static inline struct sk_buff *tcp_rtx_queue_head(const struct sock *sk)
        return skb_rb_first(&sk->tcp_rtx_queue);
 }
 
+static inline struct sk_buff *tcp_rtx_queue_tail(const struct sock *sk)
+{
+       return skb_rb_last(&sk->tcp_rtx_queue);
+}
+
 static inline struct sk_buff *tcp_write_queue_head(const struct sock *sk)
 {
        return skb_peek(&sk->sk_write_queue);
@@ -2103,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);
 
@@ -2114,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);            \
index 5846091..41b2d41 100644 (file)
@@ -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);
index c5f8a9f..4f22517 100644 (file)
@@ -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 */
index 0eeea52..e06c77d 100644 (file)
@@ -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 =
index 2d64b53..9b87e1a 100644 (file)
@@ -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;
 };
 
 /**
index c50fb29..2568cb0 100644 (file)
@@ -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;
index 3f9d6b6..c1036d1 100644 (file)
@@ -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 {
index c5188ff..bc88d6f 100644 (file)
@@ -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);
 }
index 954563e..985a5f5 100644 (file)
@@ -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);
index bded69e..6080ea0 100644 (file)
@@ -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.
index 4bb8ee1..65e4c20 100644 (file)
@@ -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.
index 3d174e2..5b8de1b 100644 (file)
@@ -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.
index 12867bb..10f00c0 100644 (file)
@@ -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.
index 16528d2..a9156b4 100644 (file)
@@ -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.
index 8ae3ad4..0038794 100644 (file)
@@ -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.
index 643f175..0b71b38 100644 (file)
@@ -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.
index 41dcabf..c47b362 100644 (file)
@@ -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.
index 9257d54..fda6e8f 100644 (file)
@@ -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.
index d25c764..dd53d36 100644 (file)
@@ -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.
index 2212add..64e92d5 100644 (file)
@@ -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>
index f3a1256..6678cf8 100644 (file)
@@ -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>
index 60d0d8b..0d1a9eb 100644 (file)
@@ -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>
index 0818f62..971cd02 100644 (file)
@@ -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>
index 2ec3cc9..cbc1f58 100644 (file)
@@ -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
 
index 1670f09..782a03e 100644 (file)
@@ -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.
  */
index d10b832..0a52b7b 100644 (file)
@@ -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.
index 070d1bc..20917c5 100644 (file)
@@ -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
index a7c1954..5e3f12d 100644 (file)
@@ -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)
 
index 6f3791c..00d787f 100644 (file)
@@ -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
 
index 2312f0e..323f0df 100644 (file)
@@ -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 */
index 75758ec..beb9a9d 100644 (file)
@@ -2863,7 +2863,7 @@ enum nl80211_attrs {
 #define NL80211_HT_CAPABILITY_LEN              26
 #define NL80211_VHT_CAPABILITY_LEN             12
 #define NL80211_HE_MIN_CAPABILITY_LEN           16
-#define NL80211_HE_MAX_CAPABILITY_LEN           51
+#define NL80211_HE_MAX_CAPABILITY_LEN           54
 #define NL80211_MAX_NR_CIPHER_SUITES           5
 #define NL80211_MAX_NR_AKM_SUITES              2
 
index 8654b24..592a0c1 100644 (file)
@@ -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.
index 782069d..4accfa7 100644 (file)
@@ -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.
index 5642c05..3cc3af1 100644 (file)
 
 #define PORT_PNX8XXX   70
 
-/* Hilscher netx */
-#define PORT_NETX      71
-
 /* SUN4V Hypervisor Console */
 #define PORT_SUNHV     72
 
index 8eb9602..c3409c8 100644 (file)
@@ -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 */
index 3c9ee30..652f169 100644 (file)
@@ -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
  *
index 26f3981..c27289f 100644 (file)
@@ -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
index 612f0c7..9cec58a 100644 (file)
@@ -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.
  *
index 9d9705c..2427bc4 100644 (file)
@@ -518,7 +518,13 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_RGBX444 v4l2_fourcc('R', 'X', '1', '2') /* 16  rrrrgggg bbbbxxxx */
 #define V4L2_PIX_FMT_ABGR444 v4l2_fourcc('A', 'B', '1', '2') /* 16  aaaabbbb ggggrrrr */
 #define V4L2_PIX_FMT_XBGR444 v4l2_fourcc('X', 'B', '1', '2') /* 16  xxxxbbbb ggggrrrr */
-#define V4L2_PIX_FMT_BGRA444 v4l2_fourcc('B', 'A', '1', '2') /* 16  bbbbgggg rrrraaaa */
+
+/*
+ * Originally this had 'BA12' as fourcc, but this clashed with the older
+ * V4L2_PIX_FMT_SGRBG12 which inexplicably used that same fourcc.
+ * So use 'GA12' instead for V4L2_PIX_FMT_BGRA444.
+ */
+#define V4L2_PIX_FMT_BGRA444 v4l2_fourcc('G', 'A', '1', '2') /* 16  bbbbgggg rrrraaaa */
 #define V4L2_PIX_FMT_BGRX444 v4l2_fourcc('B', 'X', '1', '2') /* 16  bbbbgggg rrrrxxxx */
 #define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R', 'G', 'B', 'O') /* 16  RGB-5-5-5     */
 #define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16  ARGB-1-5-5-5  */
index ba1b460..237e36a 100644 (file)
@@ -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
 
 /* 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 {
index 9a63ed6..b022787 100644 (file)
@@ -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.
  *
index 0226196..3e9da91 100644 (file)
@@ -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
 
index c36f2d7..7085c5d 100644 (file)
@@ -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
  *
index 6d701af..fb792e8 100644 (file)
@@ -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__
index 7328293..7c05a02 100644 (file)
@@ -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
index 3dd8071..7de68f1 100644 (file)
@@ -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 */
index 17c7abd..9988db6 100644 (file)
@@ -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
  *
index f39352c..9eee32f 100644 (file)
@@ -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
  *
index 1afca97..e9f6974 100644 (file)
@@ -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
index 7868990..5f4518e 100644 (file)
@@ -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.
  *
  * 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
index 4969817..98b30c1 100644 (file)
@@ -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
index fc020c0..deff972 100644 (file)
@@ -35,10 +35,10 @@ config PREEMPT_VOLUNTARY
 
          Select this if you are building a kernel for a desktop system.
 
-config PREEMPT_LL
+config PREEMPT
        bool "Preemptible Kernel (Low-Latency Desktop)"
        depends on !ARCH_NO_PREEMPT
-       select PREEMPT
+       select PREEMPTION
        select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK
        help
          This option reduces the latency of the kernel by making
@@ -58,7 +58,7 @@ config PREEMPT_LL
 config PREEMPT_RT
        bool "Fully Preemptible Kernel (Real-Time)"
        depends on EXPERT && ARCH_SUPPORTS_RT
-       select PREEMPT
+       select PREEMPTION
        help
          This option turns the kernel into a real-time kernel by replacing
          various locking primitives (spinlocks, rwlocks, etc.) with
@@ -77,6 +77,6 @@ endchoice
 config PREEMPT_COUNT
        bool
 
-config PREEMPT
+config PREEMPTION
        bool
        select PREEMPT_COUNT
index a8d923b..ef0d95a 100644 (file)
@@ -111,7 +111,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
index 5900cbb..c84d83f 100644 (file)
@@ -8616,8 +8616,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,
index f9a0ce6..c0a4c12 100644 (file)
@@ -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);
index bfc0c17..2bd410f 100644 (file)
@@ -243,8 +243,9 @@ 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 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 */
@@ -266,7 +267,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));
 }
 
index 1f628e7..b945239 100644 (file)
@@ -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);
        }
@@ -170,7 +175,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));
        }
index 026a145..0463c11 100644 (file)
@@ -11274,7 +11274,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);
 
index a75b6a7..5b4a5dc 100644 (file)
@@ -720,6 +720,7 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
        if (group_dead)
                kill_orphaned_pgrp(tsk->group_leader, NULL);
 
+       tsk->exit_state = EXIT_ZOMBIE;
        if (unlikely(tsk->ptrace)) {
                int sig = thread_group_leader(tsk) &&
                                thread_group_empty(tsk) &&
@@ -733,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))
index d8ae0f1..2852d0e 100644 (file)
@@ -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);
index 4352b08..6fef480 100644 (file)
@@ -251,11 +251,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;
index 341f521..4861cf8 100644 (file)
@@ -448,7 +448,7 @@ 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
 /*
  * Stack-trace: tightly packed array of stack backtrace
  * addresses. Protected by the graph_lock.
@@ -491,7 +491,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:
  */
@@ -2969,7 +2969,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);
 
@@ -3608,7 +3608,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 +3627,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 +4321,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;
 
index 65b6a16..bda006f 100644 (file)
@@ -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)
index edd1c08..5e06973 100644 (file)
@@ -908,6 +908,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 +1383,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_);
 
index 37524a4..bd0f0d0 100644 (file)
@@ -666,7 +666,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();
@@ -1000,6 +1004,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 +1019,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 +1038,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 +1073,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 +1094,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 +1135,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,9 +1198,11 @@ 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);
 
diff --git a/kernel/memremap.c b/kernel/memremap.c
deleted file mode 100644 (file)
index 6ee03a8..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2015 Intel Corporation. All rights reserved. */
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/kasan.h>
-#include <linux/memory_hotplug.h>
-#include <linux/mm.h>
-#include <linux/pfn_t.h>
-#include <linux/swap.h>
-#include <linux/swapops.h>
-#include <linux/types.h>
-#include <linux/wait_bit.h>
-#include <linux/xarray.h>
-
-static DEFINE_XARRAY(pgmap_array);
-#define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
-#define SECTION_SIZE (1UL << PA_SECTION_SHIFT)
-
-#ifdef CONFIG_DEV_PAGEMAP_OPS
-DEFINE_STATIC_KEY_FALSE(devmap_managed_key);
-EXPORT_SYMBOL(devmap_managed_key);
-static atomic_t devmap_managed_enable;
-
-static void devmap_managed_enable_put(void *data)
-{
-       if (atomic_dec_and_test(&devmap_managed_enable))
-               static_branch_disable(&devmap_managed_key);
-}
-
-static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
-{
-       if (!pgmap->ops || !pgmap->ops->page_free) {
-               WARN(1, "Missing page_free method\n");
-               return -EINVAL;
-       }
-
-       if (atomic_inc_return(&devmap_managed_enable) == 1)
-               static_branch_enable(&devmap_managed_key);
-       return devm_add_action_or_reset(dev, devmap_managed_enable_put, NULL);
-}
-#else
-static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
-{
-       return -EINVAL;
-}
-#endif /* CONFIG_DEV_PAGEMAP_OPS */
-
-static void pgmap_array_delete(struct resource *res)
-{
-       xa_store_range(&pgmap_array, PHYS_PFN(res->start), PHYS_PFN(res->end),
-                       NULL, GFP_KERNEL);
-       synchronize_rcu();
-}
-
-static unsigned long pfn_first(struct dev_pagemap *pgmap)
-{
-       return PHYS_PFN(pgmap->res.start) +
-               vmem_altmap_offset(pgmap_altmap(pgmap));
-}
-
-static unsigned long pfn_end(struct dev_pagemap *pgmap)
-{
-       const struct resource *res = &pgmap->res;
-
-       return (res->start + resource_size(res)) >> PAGE_SHIFT;
-}
-
-static unsigned long pfn_next(unsigned long pfn)
-{
-       if (pfn % 1024 == 0)
-               cond_resched();
-       return pfn + 1;
-}
-
-#define for_each_device_pfn(pfn, map) \
-       for (pfn = pfn_first(map); pfn < pfn_end(map); pfn = pfn_next(pfn))
-
-static void dev_pagemap_kill(struct dev_pagemap *pgmap)
-{
-       if (pgmap->ops && pgmap->ops->kill)
-               pgmap->ops->kill(pgmap);
-       else
-               percpu_ref_kill(pgmap->ref);
-}
-
-static void dev_pagemap_cleanup(struct dev_pagemap *pgmap)
-{
-       if (pgmap->ops && pgmap->ops->cleanup) {
-               pgmap->ops->cleanup(pgmap);
-       } else {
-               wait_for_completion(&pgmap->done);
-               percpu_ref_exit(pgmap->ref);
-       }
-}
-
-static void devm_memremap_pages_release(void *data)
-{
-       struct dev_pagemap *pgmap = data;
-       struct device *dev = pgmap->dev;
-       struct resource *res = &pgmap->res;
-       unsigned long pfn;
-       int nid;
-
-       dev_pagemap_kill(pgmap);
-       for_each_device_pfn(pfn, pgmap)
-               put_page(pfn_to_page(pfn));
-       dev_pagemap_cleanup(pgmap);
-
-       /* pages are dead and unused, undo the arch mapping */
-       nid = page_to_nid(pfn_to_page(PHYS_PFN(res->start)));
-
-       mem_hotplug_begin();
-       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
-               pfn = PHYS_PFN(res->start);
-               __remove_pages(page_zone(pfn_to_page(pfn)), pfn,
-                                PHYS_PFN(resource_size(res)), NULL);
-       } else {
-               arch_remove_memory(nid, res->start, resource_size(res),
-                               pgmap_altmap(pgmap));
-               kasan_remove_zero_shadow(__va(res->start), resource_size(res));
-       }
-       mem_hotplug_done();
-
-       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
-       pgmap_array_delete(res);
-       dev_WARN_ONCE(dev, pgmap->altmap.alloc,
-                     "%s: failed to free all reserved pages\n", __func__);
-}
-
-static void dev_pagemap_percpu_release(struct percpu_ref *ref)
-{
-       struct dev_pagemap *pgmap =
-               container_of(ref, struct dev_pagemap, internal_ref);
-
-       complete(&pgmap->done);
-}
-
-/**
- * devm_memremap_pages - remap and provide memmap backing for the given resource
- * @dev: hosting device for @res
- * @pgmap: pointer to a struct dev_pagemap
- *
- * Notes:
- * 1/ At a minimum the res and type members of @pgmap must be initialized
- *    by the caller before passing it to this function
- *
- * 2/ The altmap field may optionally be initialized, in which case
- *    PGMAP_ALTMAP_VALID must be set in pgmap->flags.
- *
- * 3/ The ref field may optionally be provided, in which pgmap->ref must be
- *    'live' on entry and will be killed and reaped at
- *    devm_memremap_pages_release() time, or if this routine fails.
- *
- * 4/ res is expected to be a host memory range that could feasibly be
- *    treated as a "System RAM" range, i.e. not a device mmio range, but
- *    this is not enforced.
- */
-void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
-{
-       struct resource *res = &pgmap->res;
-       struct dev_pagemap *conflict_pgmap;
-       struct mhp_restrictions restrictions = {
-               /*
-                * We do not want any optional features only our own memmap
-                */
-               .altmap = pgmap_altmap(pgmap),
-       };
-       pgprot_t pgprot = PAGE_KERNEL;
-       int error, nid, is_ram;
-       bool need_devmap_managed = true;
-
-       switch (pgmap->type) {
-       case MEMORY_DEVICE_PRIVATE:
-               if (!IS_ENABLED(CONFIG_DEVICE_PRIVATE)) {
-                       WARN(1, "Device private memory not supported\n");
-                       return ERR_PTR(-EINVAL);
-               }
-               if (!pgmap->ops || !pgmap->ops->migrate_to_ram) {
-                       WARN(1, "Missing migrate_to_ram method\n");
-                       return ERR_PTR(-EINVAL);
-               }
-               break;
-       case MEMORY_DEVICE_FS_DAX:
-               if (!IS_ENABLED(CONFIG_ZONE_DEVICE) ||
-                   IS_ENABLED(CONFIG_FS_DAX_LIMITED)) {
-                       WARN(1, "File system DAX not supported\n");
-                       return ERR_PTR(-EINVAL);
-               }
-               break;
-       case MEMORY_DEVICE_DEVDAX:
-       case MEMORY_DEVICE_PCI_P2PDMA:
-               need_devmap_managed = false;
-               break;
-       default:
-               WARN(1, "Invalid pgmap type %d\n", pgmap->type);
-               break;
-       }
-
-       if (!pgmap->ref) {
-               if (pgmap->ops && (pgmap->ops->kill || pgmap->ops->cleanup))
-                       return ERR_PTR(-EINVAL);
-
-               init_completion(&pgmap->done);
-               error = percpu_ref_init(&pgmap->internal_ref,
-                               dev_pagemap_percpu_release, 0, GFP_KERNEL);
-               if (error)
-                       return ERR_PTR(error);
-               pgmap->ref = &pgmap->internal_ref;
-       } else {
-               if (!pgmap->ops || !pgmap->ops->kill || !pgmap->ops->cleanup) {
-                       WARN(1, "Missing reference count teardown definition\n");
-                       return ERR_PTR(-EINVAL);
-               }
-       }
-
-       if (need_devmap_managed) {
-               error = devmap_managed_enable_get(dev, pgmap);
-               if (error)
-                       return ERR_PTR(error);
-       }
-
-       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->start), NULL);
-       if (conflict_pgmap) {
-               dev_WARN(dev, "Conflicting mapping in same section\n");
-               put_dev_pagemap(conflict_pgmap);
-               error = -ENOMEM;
-               goto err_array;
-       }
-
-       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->end), NULL);
-       if (conflict_pgmap) {
-               dev_WARN(dev, "Conflicting mapping in same section\n");
-               put_dev_pagemap(conflict_pgmap);
-               error = -ENOMEM;
-               goto err_array;
-       }
-
-       is_ram = region_intersects(res->start, resource_size(res),
-               IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
-
-       if (is_ram != REGION_DISJOINT) {
-               WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
-                               is_ram == REGION_MIXED ? "mixed" : "ram", res);
-               error = -ENXIO;
-               goto err_array;
-       }
-
-       pgmap->dev = dev;
-
-       error = xa_err(xa_store_range(&pgmap_array, PHYS_PFN(res->start),
-                               PHYS_PFN(res->end), pgmap, GFP_KERNEL));
-       if (error)
-               goto err_array;
-
-       nid = dev_to_node(dev);
-       if (nid < 0)
-               nid = numa_mem_id();
-
-       error = track_pfn_remap(NULL, &pgprot, PHYS_PFN(res->start), 0,
-                       resource_size(res));
-       if (error)
-               goto err_pfn_remap;
-
-       mem_hotplug_begin();
-
-       /*
-        * For device private memory we call add_pages() as we only need to
-        * allocate and initialize struct page for the device memory. More-
-        * over the device memory is un-accessible thus we do not want to
-        * create a linear mapping for the memory like arch_add_memory()
-        * would do.
-        *
-        * For all other device memory types, which are accessible by
-        * the CPU, we do want the linear mapping and thus use
-        * arch_add_memory().
-        */
-       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
-               error = add_pages(nid, PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), &restrictions);
-       } else {
-               error = kasan_add_zero_shadow(__va(res->start), resource_size(res));
-               if (error) {
-                       mem_hotplug_done();
-                       goto err_kasan;
-               }
-
-               error = arch_add_memory(nid, res->start, resource_size(res),
-                                       &restrictions);
-       }
-
-       if (!error) {
-               struct zone *zone;
-
-               zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE];
-               move_pfn_range_to_zone(zone, PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), restrictions.altmap);
-       }
-
-       mem_hotplug_done();
-       if (error)
-               goto err_add_memory;
-
-       /*
-        * Initialization of the pages has been deferred until now in order
-        * to allow us to do the work while not holding the hotplug lock.
-        */
-       memmap_init_zone_device(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
-                               PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), pgmap);
-       percpu_ref_get_many(pgmap->ref, pfn_end(pgmap) - pfn_first(pgmap));
-
-       error = devm_add_action_or_reset(dev, devm_memremap_pages_release,
-                       pgmap);
-       if (error)
-               return ERR_PTR(error);
-
-       return __va(res->start);
-
- err_add_memory:
-       kasan_remove_zero_shadow(__va(res->start), resource_size(res));
- err_kasan:
-       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
- err_pfn_remap:
-       pgmap_array_delete(res);
- err_array:
-       dev_pagemap_kill(pgmap);
-       dev_pagemap_cleanup(pgmap);
-       return ERR_PTR(error);
-}
-EXPORT_SYMBOL_GPL(devm_memremap_pages);
-
-void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap)
-{
-       devm_release_action(dev, devm_memremap_pages_release, pgmap);
-}
-EXPORT_SYMBOL_GPL(devm_memunmap_pages);
-
-unsigned long vmem_altmap_offset(struct vmem_altmap *altmap)
-{
-       /* number of pfns from base where pfn_to_page() is valid */
-       if (altmap)
-               return altmap->reserve + altmap->free;
-       return 0;
-}
-
-void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns)
-{
-       altmap->alloc -= nr_pfns;
-}
-
-/**
- * get_dev_pagemap() - take a new live reference on the dev_pagemap for @pfn
- * @pfn: page frame number to lookup page_map
- * @pgmap: optional known pgmap that already has a reference
- *
- * If @pgmap is non-NULL and covers @pfn it will be returned as-is.  If @pgmap
- * is non-NULL but does not cover @pfn the reference to it will be released.
- */
-struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
-               struct dev_pagemap *pgmap)
-{
-       resource_size_t phys = PFN_PHYS(pfn);
-
-       /*
-        * In the cached case we're already holding a live reference.
-        */
-       if (pgmap) {
-               if (phys >= pgmap->res.start && phys <= pgmap->res.end)
-                       return pgmap;
-               put_dev_pagemap(pgmap);
-       }
-
-       /* fall back to slow path lookup */
-       rcu_read_lock();
-       pgmap = xa_load(&pgmap_array, PHYS_PFN(phys));
-       if (pgmap && !percpu_ref_tryget_live(pgmap->ref))
-               pgmap = NULL;
-       rcu_read_unlock();
-
-       return pgmap;
-}
-EXPORT_SYMBOL_GPL(get_dev_pagemap);
-
-#ifdef CONFIG_DEV_PAGEMAP_OPS
-void __put_devmap_managed_page(struct page *page)
-{
-       int count = page_ref_dec_return(page);
-
-       /*
-        * If refcount is 1 then page is freed and refcount is stable as nobody
-        * holds a reference on the page.
-        */
-       if (count == 1) {
-               /* Clear Active bit in case of parallel mark_page_accessed */
-               __ClearPageActive(page);
-               __ClearPageWaiters(page);
-
-               mem_cgroup_uncharge(page);
-
-               page->pgmap->ops->page_free(page);
-       } else if (!count)
-               __put_page(page);
-}
-EXPORT_SYMBOL(__put_devmap_managed_page);
-#endif /* CONFIG_DEV_PAGEMAP_OPS */
index ef5b9f6..46122ed 100644 (file)
@@ -2088,17 +2088,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 +2182,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;
 
index 036be95..bc9cfea 100644 (file)
@@ -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;
@@ -1186,7 +1205,7 @@ void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
        p->numa_scan_period             = sysctl_numa_balancing_scan_delay;
        p->numa_work.next               = &p->numa_work;
        p->numa_faults                  = NULL;
-       p->numa_group                   = NULL;
+       RCU_INIT_POINTER(p->numa_group, NULL);
        p->last_task_numa_placement     = 0;
        p->last_sum_exec_runtime        = 0;
 
@@ -1233,7 +1252,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 +1286,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 +1430,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 +1450,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 +1631,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 +1677,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 +1790,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 +1841,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 +1875,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 +2170,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 +2188,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 +2231,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 +2239,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 +2257,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 +2292,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 +2328,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 +2390,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 +2420,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 +2480,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))
@@ -10444,18 +10498,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 */
index 7acc632..23fbbcc 100644 (file)
@@ -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);
index 91b789d..e667be6 100644 (file)
@@ -349,7 +349,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 +1885,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);
 }
index 69ebf3c..78af971 100644 (file)
@@ -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);
                /*
@@ -155,16 +162,6 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
        if (ftrace_graph_ignore_irqs())
                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.
index 4fafba1..7fa97a8 100644 (file)
@@ -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
index 095601c..29c02a9 100644 (file)
@@ -279,7 +279,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
 
index 439d641..38045d6 100644 (file)
@@ -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;
 
index 5bcc902..a4db51c 100644 (file)
@@ -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)
 {
index 42695bc..0083b5c 100644 (file)
@@ -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)
 
index 83ea6c4..6ca97a6 100644 (file)
@@ -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) {
index 62d19f2..9729f27 100644 (file)
@@ -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);
 
index 2d1c1f2..e630e7f 100644 (file)
@@ -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 */
index 338e528..d0b295c 100644 (file)
@@ -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
index 83a7b61..798275a 100644 (file)
@@ -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,12 +113,13 @@ 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)
 {
@@ -128,15 +130,17 @@ struct page *balloon_page_alloc(void)
 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 +155,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 +184,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 +237,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;
index 9e1b9ac..952dc2f 100644 (file)
@@ -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);
index e1eedef..16b6731 100644 (file)
--- 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))
index dbbd518..6e9e8cc 100644 (file)
 /* 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 {
index 2a9bbdd..c73f099 100644 (file)
@@ -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/memremap.c b/mm/memremap.c
new file mode 100644 (file)
index 0000000..8643265
--- /dev/null
@@ -0,0 +1,411 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2015 Intel Corporation. All rights reserved. */
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kasan.h>
+#include <linux/memory_hotplug.h>
+#include <linux/mm.h>
+#include <linux/pfn_t.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
+#include <linux/types.h>
+#include <linux/wait_bit.h>
+#include <linux/xarray.h>
+
+static DEFINE_XARRAY(pgmap_array);
+#define SECTION_MASK ~((1UL << PA_SECTION_SHIFT) - 1)
+#define SECTION_SIZE (1UL << PA_SECTION_SHIFT)
+
+#ifdef CONFIG_DEV_PAGEMAP_OPS
+DEFINE_STATIC_KEY_FALSE(devmap_managed_key);
+EXPORT_SYMBOL(devmap_managed_key);
+static atomic_t devmap_managed_enable;
+
+static void devmap_managed_enable_put(void *data)
+{
+       if (atomic_dec_and_test(&devmap_managed_enable))
+               static_branch_disable(&devmap_managed_key);
+}
+
+static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
+{
+       if (!pgmap->ops || !pgmap->ops->page_free) {
+               WARN(1, "Missing page_free method\n");
+               return -EINVAL;
+       }
+
+       if (atomic_inc_return(&devmap_managed_enable) == 1)
+               static_branch_enable(&devmap_managed_key);
+       return devm_add_action_or_reset(dev, devmap_managed_enable_put, NULL);
+}
+#else
+static int devmap_managed_enable_get(struct device *dev, struct dev_pagemap *pgmap)
+{
+       return -EINVAL;
+}
+#endif /* CONFIG_DEV_PAGEMAP_OPS */
+
+static void pgmap_array_delete(struct resource *res)
+{
+       xa_store_range(&pgmap_array, PHYS_PFN(res->start), PHYS_PFN(res->end),
+                       NULL, GFP_KERNEL);
+       synchronize_rcu();
+}
+
+static unsigned long pfn_first(struct dev_pagemap *pgmap)
+{
+       return PHYS_PFN(pgmap->res.start) +
+               vmem_altmap_offset(pgmap_altmap(pgmap));
+}
+
+static unsigned long pfn_end(struct dev_pagemap *pgmap)
+{
+       const struct resource *res = &pgmap->res;
+
+       return (res->start + resource_size(res)) >> PAGE_SHIFT;
+}
+
+static unsigned long pfn_next(unsigned long pfn)
+{
+       if (pfn % 1024 == 0)
+               cond_resched();
+       return pfn + 1;
+}
+
+#define for_each_device_pfn(pfn, map) \
+       for (pfn = pfn_first(map); pfn < pfn_end(map); pfn = pfn_next(pfn))
+
+static void dev_pagemap_kill(struct dev_pagemap *pgmap)
+{
+       if (pgmap->ops && pgmap->ops->kill)
+               pgmap->ops->kill(pgmap);
+       else
+               percpu_ref_kill(pgmap->ref);
+}
+
+static void dev_pagemap_cleanup(struct dev_pagemap *pgmap)
+{
+       if (pgmap->ops && pgmap->ops->cleanup) {
+               pgmap->ops->cleanup(pgmap);
+       } else {
+               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)
+{
+       struct dev_pagemap *pgmap = data;
+       struct device *dev = pgmap->dev;
+       struct resource *res = &pgmap->res;
+       unsigned long pfn;
+       int nid;
+
+       dev_pagemap_kill(pgmap);
+       for_each_device_pfn(pfn, pgmap)
+               put_page(pfn_to_page(pfn));
+       dev_pagemap_cleanup(pgmap);
+
+       /* pages are dead and unused, undo the arch mapping */
+       nid = page_to_nid(pfn_to_page(PHYS_PFN(res->start)));
+
+       mem_hotplug_begin();
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+               pfn = PHYS_PFN(res->start);
+               __remove_pages(page_zone(pfn_to_page(pfn)), pfn,
+                                PHYS_PFN(resource_size(res)), NULL);
+       } else {
+               arch_remove_memory(nid, res->start, resource_size(res),
+                               pgmap_altmap(pgmap));
+               kasan_remove_zero_shadow(__va(res->start), resource_size(res));
+       }
+       mem_hotplug_done();
+
+       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
+       pgmap_array_delete(res);
+       dev_WARN_ONCE(dev, pgmap->altmap.alloc,
+                     "%s: failed to free all reserved pages\n", __func__);
+}
+
+static void dev_pagemap_percpu_release(struct percpu_ref *ref)
+{
+       struct dev_pagemap *pgmap =
+               container_of(ref, struct dev_pagemap, internal_ref);
+
+       complete(&pgmap->done);
+}
+
+/**
+ * devm_memremap_pages - remap and provide memmap backing for the given resource
+ * @dev: hosting device for @res
+ * @pgmap: pointer to a struct dev_pagemap
+ *
+ * Notes:
+ * 1/ At a minimum the res and type members of @pgmap must be initialized
+ *    by the caller before passing it to this function
+ *
+ * 2/ The altmap field may optionally be initialized, in which case
+ *    PGMAP_ALTMAP_VALID must be set in pgmap->flags.
+ *
+ * 3/ The ref field may optionally be provided, in which pgmap->ref must be
+ *    'live' on entry and will be killed and reaped at
+ *    devm_memremap_pages_release() time, or if this routine fails.
+ *
+ * 4/ res is expected to be a host memory range that could feasibly be
+ *    treated as a "System RAM" range, i.e. not a device mmio range, but
+ *    this is not enforced.
+ */
+void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
+{
+       struct resource *res = &pgmap->res;
+       struct dev_pagemap *conflict_pgmap;
+       struct mhp_restrictions restrictions = {
+               /*
+                * We do not want any optional features only our own memmap
+                */
+               .altmap = pgmap_altmap(pgmap),
+       };
+       pgprot_t pgprot = PAGE_KERNEL;
+       int error, nid, is_ram;
+       bool need_devmap_managed = true;
+
+       switch (pgmap->type) {
+       case MEMORY_DEVICE_PRIVATE:
+               if (!IS_ENABLED(CONFIG_DEVICE_PRIVATE)) {
+                       WARN(1, "Device private memory not supported\n");
+                       return ERR_PTR(-EINVAL);
+               }
+               if (!pgmap->ops || !pgmap->ops->migrate_to_ram) {
+                       WARN(1, "Missing migrate_to_ram method\n");
+                       return ERR_PTR(-EINVAL);
+               }
+               break;
+       case MEMORY_DEVICE_FS_DAX:
+               if (!IS_ENABLED(CONFIG_ZONE_DEVICE) ||
+                   IS_ENABLED(CONFIG_FS_DAX_LIMITED)) {
+                       WARN(1, "File system DAX not supported\n");
+                       return ERR_PTR(-EINVAL);
+               }
+               break;
+       case MEMORY_DEVICE_DEVDAX:
+       case MEMORY_DEVICE_PCI_P2PDMA:
+               need_devmap_managed = false;
+               break;
+       default:
+               WARN(1, "Invalid pgmap type %d\n", pgmap->type);
+               break;
+       }
+
+       if (!pgmap->ref) {
+               if (pgmap->ops && (pgmap->ops->kill || pgmap->ops->cleanup))
+                       return ERR_PTR(-EINVAL);
+
+               init_completion(&pgmap->done);
+               error = percpu_ref_init(&pgmap->internal_ref,
+                               dev_pagemap_percpu_release, 0, GFP_KERNEL);
+               if (error)
+                       return ERR_PTR(error);
+               pgmap->ref = &pgmap->internal_ref;
+       } else {
+               if (!pgmap->ops || !pgmap->ops->kill || !pgmap->ops->cleanup) {
+                       WARN(1, "Missing reference count teardown definition\n");
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       if (need_devmap_managed) {
+               error = devmap_managed_enable_get(dev, pgmap);
+               if (error)
+                       return ERR_PTR(error);
+       }
+
+       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->start), NULL);
+       if (conflict_pgmap) {
+               dev_WARN(dev, "Conflicting mapping in same section\n");
+               put_dev_pagemap(conflict_pgmap);
+               error = -ENOMEM;
+               goto err_array;
+       }
+
+       conflict_pgmap = get_dev_pagemap(PHYS_PFN(res->end), NULL);
+       if (conflict_pgmap) {
+               dev_WARN(dev, "Conflicting mapping in same section\n");
+               put_dev_pagemap(conflict_pgmap);
+               error = -ENOMEM;
+               goto err_array;
+       }
+
+       is_ram = region_intersects(res->start, resource_size(res),
+               IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
+
+       if (is_ram != REGION_DISJOINT) {
+               WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
+                               is_ram == REGION_MIXED ? "mixed" : "ram", res);
+               error = -ENXIO;
+               goto err_array;
+       }
+
+       pgmap->dev = dev;
+
+       error = xa_err(xa_store_range(&pgmap_array, PHYS_PFN(res->start),
+                               PHYS_PFN(res->end), pgmap, GFP_KERNEL));
+       if (error)
+               goto err_array;
+
+       nid = dev_to_node(dev);
+       if (nid < 0)
+               nid = numa_mem_id();
+
+       error = track_pfn_remap(NULL, &pgprot, PHYS_PFN(res->start), 0,
+                       resource_size(res));
+       if (error)
+               goto err_pfn_remap;
+
+       mem_hotplug_begin();
+
+       /*
+        * For device private memory we call add_pages() as we only need to
+        * allocate and initialize struct page for the device memory. More-
+        * over the device memory is un-accessible thus we do not want to
+        * create a linear mapping for the memory like arch_add_memory()
+        * would do.
+        *
+        * For all other device memory types, which are accessible by
+        * the CPU, we do want the linear mapping and thus use
+        * arch_add_memory().
+        */
+       if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
+               error = add_pages(nid, PHYS_PFN(res->start),
+                               PHYS_PFN(resource_size(res)), &restrictions);
+       } else {
+               error = kasan_add_zero_shadow(__va(res->start), resource_size(res));
+               if (error) {
+                       mem_hotplug_done();
+                       goto err_kasan;
+               }
+
+               error = arch_add_memory(nid, res->start, resource_size(res),
+                                       &restrictions);
+       }
+
+       if (!error) {
+               struct zone *zone;
+
+               zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE];
+               move_pfn_range_to_zone(zone, PHYS_PFN(res->start),
+                               PHYS_PFN(resource_size(res)), restrictions.altmap);
+       }
+
+       mem_hotplug_done();
+       if (error)
+               goto err_add_memory;
+
+       /*
+        * Initialization of the pages has been deferred until now in order
+        * to allow us to do the work while not holding the hotplug lock.
+        */
+       memmap_init_zone_device(&NODE_DATA(nid)->node_zones[ZONE_DEVICE],
+                               PHYS_PFN(res->start),
+                               PHYS_PFN(resource_size(res)), pgmap);
+       percpu_ref_get_many(pgmap->ref, pfn_end(pgmap) - pfn_first(pgmap));
+
+       error = devm_add_action_or_reset(dev, devm_memremap_pages_release,
+                       pgmap);
+       if (error)
+               return ERR_PTR(error);
+
+       return __va(res->start);
+
+ err_add_memory:
+       kasan_remove_zero_shadow(__va(res->start), resource_size(res));
+ err_kasan:
+       untrack_pfn(NULL, PHYS_PFN(res->start), resource_size(res));
+ err_pfn_remap:
+       pgmap_array_delete(res);
+ err_array:
+       dev_pagemap_kill(pgmap);
+       dev_pagemap_cleanup(pgmap);
+       return ERR_PTR(error);
+}
+EXPORT_SYMBOL_GPL(devm_memremap_pages);
+
+void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap)
+{
+       devm_release_action(dev, devm_memremap_pages_release, pgmap);
+}
+EXPORT_SYMBOL_GPL(devm_memunmap_pages);
+
+unsigned long vmem_altmap_offset(struct vmem_altmap *altmap)
+{
+       /* number of pfns from base where pfn_to_page() is valid */
+       if (altmap)
+               return altmap->reserve + altmap->free;
+       return 0;
+}
+
+void vmem_altmap_free(struct vmem_altmap *altmap, unsigned long nr_pfns)
+{
+       altmap->alloc -= nr_pfns;
+}
+
+/**
+ * get_dev_pagemap() - take a new live reference on the dev_pagemap for @pfn
+ * @pfn: page frame number to lookup page_map
+ * @pgmap: optional known pgmap that already has a reference
+ *
+ * If @pgmap is non-NULL and covers @pfn it will be returned as-is.  If @pgmap
+ * is non-NULL but does not cover @pfn the reference to it will be released.
+ */
+struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
+               struct dev_pagemap *pgmap)
+{
+       resource_size_t phys = PFN_PHYS(pfn);
+
+       /*
+        * In the cached case we're already holding a live reference.
+        */
+       if (pgmap) {
+               if (phys >= pgmap->res.start && phys <= pgmap->res.end)
+                       return pgmap;
+               put_dev_pagemap(pgmap);
+       }
+
+       /* fall back to slow path lookup */
+       rcu_read_lock();
+       pgmap = xa_load(&pgmap_array, PHYS_PFN(phys));
+       if (pgmap && !percpu_ref_tryget_live(pgmap->ref))
+               pgmap = NULL;
+       rcu_read_unlock();
+
+       return pgmap;
+}
+EXPORT_SYMBOL_GPL(get_dev_pagemap);
+
+#ifdef CONFIG_DEV_PAGEMAP_OPS
+void __put_devmap_managed_page(struct page *page)
+{
+       int count = page_ref_dec_return(page);
+
+       /*
+        * If refcount is 1 then page is freed and refcount is stable as nobody
+        * holds a reference on the page.
+        */
+       if (count == 1) {
+               /* Clear Active bit in case of parallel mark_page_accessed */
+               __ClearPageActive(page);
+               __ClearPageWaiters(page);
+
+               mem_cgroup_uncharge(page);
+
+               page->pgmap->ops->page_free(page);
+       } else if (!count)
+               __put_page(page);
+}
+EXPORT_SYMBOL(__put_devmap_managed_page);
+#endif /* CONFIG_DEV_PAGEMAP_OPS */
index 8992741..a42858d 100644 (file)
@@ -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,
index e6c030e..8834563 100644 (file)
--- 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()
index 4fa8d84..e0fc963 100644 (file)
@@ -1258,6 +1258,12 @@ static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
        if (unlikely(valist == NULL))
                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)
 {
index 44df66a..dbdc46a 100644 (file)
@@ -699,7 +699,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))
index d164f63..8a8f9e5 100644 (file)
@@ -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 */
index 3d8deac..f8cac37 100644 (file)
@@ -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);
index e8cf03b..646504d 100644 (file)
@@ -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
 
index 021cc9f..f5b2aee 100644 (file)
@@ -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. */
index 154fa55..5040fe4 100644 (file)
@@ -6,7 +6,7 @@
 menuconfig NF_TABLES_BRIDGE
        depends on BRIDGE && NETFILTER && NF_TABLES
        select NETFILTER_FAMILY_BRIDGE
-       bool "Ethernet Bridge nf_tables support"
+       tristate "Ethernet Bridge nf_tables support"
 
 if NF_TABLES_BRIDGE
 
@@ -25,6 +25,8 @@ config NF_LOG_BRIDGE
        tristate "Bridge packet logging"
        select NF_LOG_COMMON
 
+endif # NF_TABLES_BRIDGE
+
 config NF_CONNTRACK_BRIDGE
        tristate "IPv4/IPV6 bridge connection tracking support"
        depends on NF_CONNTRACK
@@ -39,8 +41,6 @@ config NF_CONNTRACK_BRIDGE
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-endif # NF_TABLES_BRIDGE
-
 menuconfig BRIDGE_NF_EBTABLES
        tristate "Ethernet Bridge tables (ebtables) support"
        depends on BRIDGE && NETFILTER && NETFILTER_XTABLES
index 963dfdc..c8177a8 100644 (file)
@@ -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;
index bed66f5..1804e86 100644 (file)
@@ -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;
@@ -61,13 +57,11 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
                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;
 }
index 5275ddf..7271105 100644 (file)
@@ -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)
index fc676b2..0891f49 100644 (file)
@@ -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.
@@ -9701,6 +9706,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",
index 4e2a79b..7878f91 100644 (file)
@@ -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),
index 76f8db3..d63b970 100644 (file)
@@ -165,7 +165,7 @@ void flow_rule_match_enc_opts(const struct flow_rule *rule,
 }
 EXPORT_SYMBOL(flow_rule_match_enc_opts);
 
-struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
                                          void *cb_ident, void *cb_priv,
                                          void (*release)(void *cb_priv))
 {
@@ -175,7 +175,6 @@ struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
        if (!block_cb)
                return ERR_PTR(-ENOMEM);
 
-       block_cb->net = net;
        block_cb->cb = cb;
        block_cb->cb_ident = cb_ident;
        block_cb->cb_priv = cb_priv;
@@ -194,14 +193,13 @@ void flow_block_cb_free(struct flow_block_cb *block_cb)
 }
 EXPORT_SYMBOL(flow_block_cb_free);
 
-struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *f,
-                                          tc_setup_cb_t *cb, void *cb_ident)
+struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
+                                          flow_setup_cb_t *cb, void *cb_ident)
 {
        struct flow_block_cb *block_cb;
 
-       list_for_each_entry(block_cb, f->driver_block_list, driver_list) {
-               if (block_cb->net == f->net &&
-                   block_cb->cb == cb &&
+       list_for_each_entry(block_cb, &block->cb_list, list) {
+               if (block_cb->cb == cb &&
                    block_cb->cb_ident == cb_ident)
                        return block_cb;
        }
@@ -228,7 +226,7 @@ unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb)
 }
 EXPORT_SYMBOL(flow_block_cb_decref);
 
-bool flow_block_cb_is_busy(tc_setup_cb_t *cb, void *cb_ident,
+bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident,
                           struct list_head *driver_block_list)
 {
        struct flow_block_cb *block_cb;
@@ -245,7 +243,8 @@ EXPORT_SYMBOL(flow_block_cb_is_busy);
 
 int flow_block_cb_setup_simple(struct flow_block_offload *f,
                               struct list_head *driver_block_list,
-                              tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
+                              flow_setup_cb_t *cb,
+                              void *cb_ident, void *cb_priv,
                               bool ingress_only)
 {
        struct flow_block_cb *block_cb;
@@ -261,8 +260,7 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
                if (flow_block_cb_is_busy(cb, cb_ident, driver_block_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, cb_ident,
-                                              cb_priv, NULL);
+               block_cb = flow_block_cb_alloc(cb, cb_ident, cb_priv, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
 
@@ -270,7 +268,7 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
                list_add_tail(&block_cb->driver_list, driver_block_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, cb, cb_ident);
+               block_cb = flow_block_cb_lookup(f->block, cb, cb_ident);
                if (!block_cb)
                        return -ENOENT;
 
index 93bffaa..6832eeb 100644 (file)
@@ -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);
index 52d4fae..1330a74 100644 (file)
@@ -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)
index 614c38e..33f4117 100644 (file)
@@ -951,7 +951,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
                                    struct flow_block_offload *f)
 {
        struct flow_block_cb *block_cb;
-       tc_setup_cb_t *cb;
+       flow_setup_cb_t *cb;
 
        if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
                cb = dsa_slave_setup_tc_block_cb_ig;
@@ -967,7 +967,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
                if (flow_block_cb_is_busy(cb, dev, &dsa_slave_block_cb_list))
                        return -EBUSY;
 
-               block_cb = flow_block_cb_alloc(f->net, cb, dev, dev, NULL);
+               block_cb = flow_block_cb_alloc(cb, dev, dev, NULL);
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
 
@@ -975,7 +975,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
                list_add_tail(&block_cb->driver_list, &dsa_slave_block_cb_list);
                return 0;
        case FLOW_BLOCK_UNBIND:
-               block_cb = flow_block_cb_lookup(f, cb, dev);
+               block_cb = flow_block_cb_lookup(f->block, cb, dev);
                if (!block_cb)
                        return -ENOENT;
 
index 26363d7..47ee881 100644 (file)
@@ -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);
        }
index d666756..a999451 100644 (file)
@@ -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;
index 43adfc1..2f01cf6 100644 (file)
@@ -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;
index 4d6bf7a..6bdb1ab 100644 (file)
@@ -416,8 +416,8 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par)
             ctinfo == IP_CT_RELATED_REPLY))
                return XT_CONTINUE;
 
-       /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
-        * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
+       /* nf_conntrack_proto_icmp guarantees us that we only have ICMP_ECHO,
+        * TIMESTAMP, INFO_REQUEST or ICMP_ADDRESS type icmp packets from here
         * on, which all have an ID field [relevant for hashing]. */
 
        hash = clusterip_hashfn(skb, cipinfo->config);
index 8e7f84e..0e70f3f 100644 (file)
@@ -36,6 +36,8 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
                        opts.options |= XT_SYNPROXY_OPT_ECN;
 
                opts.options &= info->options;
+               opts.mss_encode = opts.mss;
+               opts.mss = info->mss;
                if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP)
                        synproxy_init_timestamp_cookie(info, &opts);
                else
index 5903167..cc23f1c 100644 (file)
@@ -78,6 +78,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
        flow.flowi4_tos = RT_TOS(iph->tos);
        flow.flowi4_scope = RT_SCOPE_UNIVERSE;
+       flow.flowi4_oif = l3mdev_master_ifindex_rcu(xt_in(par));
 
        return rpfilter_lookup_reverse(xt_net(par), &flow, xt_in(par), info->flags) ^ invert;
 }
index 87b711f..3e2685c 100644 (file)
@@ -221,11 +221,11 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
-               ret = nf_ct_expect_related(rtp_exp);
+               ret = nf_ct_expect_related(rtp_exp, 0);
                if (ret == 0) {
                        rtcp_exp->tuple.dst.u.udp.port =
                            htons(nated_port + 1);
-                       ret = nf_ct_expect_related(rtcp_exp);
+                       ret = nf_ct_expect_related(rtcp_exp, 0);
                        if (ret == 0)
                                break;
                        else if (ret == -EBUSY) {
@@ -296,7 +296,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -352,7 +352,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -444,7 +444,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -537,7 +537,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(nated_port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
index 4af1f5d..6e4afc4 100644 (file)
@@ -1288,6 +1288,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *buff;
        int nsize, old_factor;
+       long limit;
        int nlen;
        u8 flags;
 
@@ -1298,8 +1299,16 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue,
        if (nsize < 0)
                nsize = 0;
 
-       if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf &&
-                    tcp_queue != TCP_FRAG_IN_WRITE_QUEUE)) {
+       /* tcp_sendmsg() can overshoot sk_wmem_queued by one full size skb.
+        * We need some allowance to not penalize applications setting small
+        * SO_SNDBUF values.
+        * Also allow first and last skb in retransmit queue to be split.
+        */
+       limit = sk->sk_sndbuf + 2 * SKB_TRUESIZE(GSO_MAX_SIZE);
+       if (unlikely((sk->sk_wmem_queued >> 1) > limit &&
+                    tcp_queue != TCP_FRAG_IN_WRITE_QUEUE &&
+                    skb != tcp_rtx_queue_head(sk) &&
+                    skb != tcp_rtx_queue_tail(sk))) {
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG);
                return -ENOMEM;
        }
index 3d8a1d8..4849edb 100644 (file)
@@ -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);
index c2049c7..dd2d0b9 100644 (file)
@@ -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;
index 3134fbb..754a484 100644 (file)
@@ -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,
index e77ea1e..5cdb4a6 100644 (file)
@@ -36,6 +36,8 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
                        opts.options |= XT_SYNPROXY_OPT_ECN;
 
                opts.options &= info->options;
+               opts.mss_encode = opts.mss;
+               opts.mss = info->mss;
                if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP)
                        synproxy_init_timestamp_cookie(info, &opts);
                else
index 6bcaf73..d800801 100644 (file)
@@ -55,7 +55,9 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
        if (rpfilter_addr_linklocal(&iph->saddr)) {
                lookup_flags |= RT6_LOOKUP_F_IFACE;
                fl6.flowi6_oif = dev->ifindex;
-       } else if ((flags & XT_RPFILTER_LOOSE) == 0)
+       /* Set flowi6_oif for vrf devices to lookup route in l3mdev domain. */
+       } else if (netif_is_l3_master(dev) || netif_is_l3_slave(dev) ||
+                 (flags & XT_RPFILTER_LOOSE) == 0)
                fl6.flowi6_oif = dev->ifindex;
 
        rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags);
@@ -70,7 +72,9 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
                goto out;
        }
 
-       if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
+       if (rt->rt6i_idev->dev == dev ||
+           l3mdev_master_ifindex_rcu(rt->rt6i_idev->dev) == dev->ifindex ||
+           (flags & XT_RPFILTER_LOOSE))
                ret = true;
  out:
        ip6_rt_put(rt);
index e49fec7..fd059e0 100644 (file)
@@ -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;
index 09e1694..ebb62a4 100644 (file)
@@ -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;
index 1d0e590..c54cb59 100644 (file)
@@ -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 = {
index 76cc9e9..4d45806 100644 (file)
@@ -936,8 +936,10 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 
        err = ieee80211_set_probe_resp(sdata, params->probe_resp,
                                       params->probe_resp_len, csa);
-       if (err < 0)
+       if (err < 0) {
+               kfree(new);
                return err;
+       }
        if (err == 0)
                changed |= BSS_CHANGED_AP_PROBE_RESP;
 
@@ -949,8 +951,10 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
                                                         params->civicloc,
                                                         params->civicloc_len);
 
-               if (err < 0)
+               if (err < 0) {
+                       kfree(new);
                        return err;
+               }
 
                changed |= BSS_CHANGED_FTM_RESPONDER;
        }
index acd4afb..c9a8a24 100644 (file)
@@ -187,11 +187,16 @@ int drv_conf_tx(struct ieee80211_local *local,
        if (!check_sdata_in_driver(sdata))
                return -EIO;
 
-       if (WARN_ONCE(params->cw_min == 0 ||
-                     params->cw_min > params->cw_max,
-                     "%s: invalid CW_min/CW_max: %d/%d\n",
-                     sdata->name, params->cw_min, params->cw_max))
+       if (params->cw_min == 0 || params->cw_min > params->cw_max) {
+               /*
+                * If we can't configure hardware anyway, don't warn. We may
+                * never have initialized the CW parameters.
+                */
+               WARN_ONCE(local->ops->conf_tx,
+                         "%s: invalid CW_min/CW_max: %d/%d\n",
+                         sdata->name, params->cw_min, params->cw_max);
                return -EINVAL;
+       }
 
        trace_drv_conf_tx(local, sdata, ac, params);
        if (local->ops->conf_tx)
index 06aac0a..8dc6580 100644 (file)
@@ -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;
 }
 
index a99ad03..4c888dc 100644 (file)
@@ -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",
index 1b224fa..ad1e581 100644 (file)
@@ -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]++;
index 32a45c0..0d65f4d 100644 (file)
@@ -223,8 +223,6 @@ config NF_CONNTRACK_FTP
          of Network Address Translation on them.
 
          This is FTP support on Layer 3 independent connection tracking.
-         Layer 3 independent connection tracking is experimental scheme
-         which generalize ip_conntrack to support other layer 3 protocols.
 
          To compile it as a module, choose M here.  If unsure, say N.
 
@@ -338,7 +336,7 @@ config NF_CONNTRACK_SIP
        help
          SIP is an application-layer control protocol that can establish,
          modify, and terminate multimedia sessions (conferences) such as
-         Internet telephony calls. With the ip_conntrack_sip and
+         Internet telephony calls. With the nf_conntrack_sip and
          the nf_nat_sip modules you can support the protocol on a connection
          tracking/NATing firewall.
 
@@ -1313,7 +1311,7 @@ config NETFILTER_XT_MATCH_HELPER
        depends on NETFILTER_ADVANCED
        help
          Helper matching allows you to match packets in dynamic connections
-         tracked by a conntrack-helper, ie. ip_conntrack_ftp
+         tracked by a conntrack-helper, ie. nf_conntrack_ftp
 
          To compile it as a module, choose M here.  If unsure, say Y.
 
index ca7ac4a..1d4e633 100644 (file)
@@ -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);
index 2e15185..e64d5f9 100644 (file)
@@ -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;
        }
index faf59b6..24d8f4d 100644 (file)
@@ -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);
index 4035419..08adcb2 100644 (file)
@@ -231,7 +231,7 @@ void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
 
        IP_VS_DBG_BUF(7, "%s: ct=%p, expect tuple=" FMT_TUPLE "\n",
                      __func__, ct, ARG_TUPLE(&exp->tuple));
-       nf_ct_expect_related(exp);
+       nf_ct_expect_related(exp, 0);
        nf_ct_expect_put(exp);
 }
 EXPORT_SYMBOL(ip_vs_nfct_expect_related);
index 42ee659..d011d2e 100644 (file)
@@ -159,7 +159,7 @@ static int amanda_help(struct sk_buff *skb,
                if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
                        ret = nf_nat_amanda(skb, ctinfo, protoff,
                                            off - dataoff, len, exp);
-               else if (nf_ct_expect_related(exp) != 0) {
+               else if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                }
index 921a7b9..1ba6bec 100644 (file)
@@ -68,7 +68,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
        exp->class                = NF_CT_EXPECT_CLASS_DEFAULT;
        exp->helper               = NULL;
 
-       nf_ct_expect_related(exp);
+       nf_ct_expect_related(exp, 0);
        nf_ct_expect_put(exp);
 
        nf_ct_refresh(ct, skb, timeout * HZ);
index bdfeace..a542761 100644 (file)
@@ -1817,9 +1817,7 @@ EXPORT_SYMBOL_GPL(nf_ct_kill_acct);
 #include <linux/netfilter/nfnetlink_conntrack.h>
 #include <linux/mutex.h>
 
-/* Generic function for tcp/udp/sctp/dccp and alike. This needs to be
- * in ip_conntrack_core, since we don't want the protocols to autoload
- * or depend on ctnetlink */
+/* Generic function for tcp/udp/sctp/dccp and alike. */
 int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
                               const struct nf_conntrack_tuple *tuple)
 {
index ffd1f49..65364de 100644 (file)
@@ -249,13 +249,22 @@ static inline int expect_clash(const struct nf_conntrack_expect *a,
 static inline int expect_matches(const struct nf_conntrack_expect *a,
                                 const struct nf_conntrack_expect *b)
 {
-       return a->master == b->master &&
-              nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
+       return nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
               nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
               net_eq(nf_ct_net(a->master), nf_ct_net(b->master)) &&
               nf_ct_zone_equal_any(a->master, nf_ct_zone(b->master));
 }
 
+static bool master_matches(const struct nf_conntrack_expect *a,
+                          const struct nf_conntrack_expect *b,
+                          unsigned int flags)
+{
+       if (flags & NF_CT_EXP_F_SKIP_MASTER)
+               return true;
+
+       return a->master == b->master;
+}
+
 /* Generally a bad idea to call this: could have matched already. */
 void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
 {
@@ -399,7 +408,8 @@ static void evict_oldest_expect(struct nf_conn *master,
                nf_ct_remove_expect(last);
 }
 
-static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
+static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect,
+                                      unsigned int flags)
 {
        const struct nf_conntrack_expect_policy *p;
        struct nf_conntrack_expect *i;
@@ -417,8 +427,10 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
        }
        h = nf_ct_expect_dst_hash(net, &expect->tuple);
        hlist_for_each_entry_safe(i, next, &nf_ct_expect_hash[h], hnode) {
-               if (expect_matches(i, expect)) {
-                       if (i->class != expect->class)
+               if (master_matches(i, expect, flags) &&
+                   expect_matches(i, expect)) {
+                       if (i->class != expect->class ||
+                           i->master != expect->master)
                                return -EALREADY;
 
                        if (nf_ct_remove_expect(i))
@@ -453,12 +465,12 @@ out:
 }
 
 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
-                               u32 portid, int report)
+                               u32 portid, int report, unsigned int flags)
 {
        int ret;
 
        spin_lock_bh(&nf_conntrack_expect_lock);
-       ret = __nf_ct_expect_check(expect);
+       ret = __nf_ct_expect_check(expect, flags);
        if (ret < 0)
                goto out;
 
index 8c6c11b..0ecb3e2 100644 (file)
@@ -525,7 +525,7 @@ skip_nl_seq:
                                 protoff, matchoff, matchlen, exp);
        else {
                /* Can't expect this?  Best to drop packet now. */
-               if (nf_ct_expect_related(exp) != 0) {
+               if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                } else
index 8f6ba81..573cb44 100644 (file)
@@ -1,11 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
- *                                  conntrack/NAT module.
+ * BER and PER decoding library for H.323 conntrack/NAT module.
  *
  * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
- * See ip_conntrack_helper_h323_asn1.h for details.
+ * See nf_conntrack_helper_h323_asn1.h for details.
  */
 
 #ifdef __KERNEL__
index 6497e5f..8ba037b 100644 (file)
@@ -305,8 +305,8 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
                ret = nat_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
                                   taddr, port, rtp_port, rtp_exp, rtcp_exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(rtp_exp) == 0) {
-                       if (nf_ct_expect_related(rtcp_exp) == 0) {
+               if (nf_ct_expect_related(rtp_exp, 0) == 0) {
+                       if (nf_ct_expect_related(rtcp_exp, 0) == 0) {
                                pr_debug("nf_ct_h323: expect RTP ");
                                nf_ct_dump_tuple(&rtp_exp->tuple);
                                pr_debug("nf_ct_h323: expect RTCP ");
@@ -364,7 +364,7 @@ static int expect_t120(struct sk_buff *skb,
                ret = nat_t120(skb, ct, ctinfo, protoff, data, dataoff, taddr,
                               port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_h323: expect T.120 ");
                        nf_ct_dump_tuple(&exp->tuple);
                } else
@@ -701,7 +701,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
                ret = nat_h245(skb, ct, ctinfo, protoff, data, dataoff, taddr,
                               port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_q931: expect H.245 ");
                        nf_ct_dump_tuple(&exp->tuple);
                } else
@@ -825,7 +825,7 @@ static int expect_callforwarding(struct sk_buff *skb,
                                         protoff, data, dataoff,
                                         taddr, port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_q931: expect Call Forwarding ");
                        nf_ct_dump_tuple(&exp->tuple);
                } else
@@ -1284,7 +1284,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
                ret = nat_q931(skb, ct, ctinfo, protoff, data,
                               taddr, i, port, exp);
        } else {                /* Conntrack only */
-               if (nf_ct_expect_related(exp) == 0) {
+               if (nf_ct_expect_related(exp, 0) == 0) {
                        pr_debug("nf_ct_ras: expect Q.931 ");
                        nf_ct_dump_tuple(&exp->tuple);
 
@@ -1349,7 +1349,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
                          IPPROTO_UDP, NULL, &port);
        exp->helper = nf_conntrack_helper_ras;
 
-       if (nf_ct_expect_related(exp) == 0) {
+       if (nf_ct_expect_related(exp, 0) == 0) {
                pr_debug("nf_ct_ras: expect RAS ");
                nf_ct_dump_tuple(&exp->tuple);
        } else
@@ -1561,7 +1561,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
        exp->flags = NF_CT_EXPECT_PERMANENT;
        exp->helper = nf_conntrack_helper_q931;
 
-       if (nf_ct_expect_related(exp) == 0) {
+       if (nf_ct_expect_related(exp, 0) == 0) {
                pr_debug("nf_ct_ras: expect Q.931 ");
                nf_ct_dump_tuple(&exp->tuple);
        } else
@@ -1615,7 +1615,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
        exp->flags = NF_CT_EXPECT_PERMANENT;
        exp->helper = nf_conntrack_helper_q931;
 
-       if (nf_ct_expect_related(exp) == 0) {
+       if (nf_ct_expect_related(exp, 0) == 0) {
                pr_debug("nf_ct_ras: expect Q.931 ");
                nf_ct_dump_tuple(&exp->tuple);
        } else
index 7ac156f..e40988a 100644 (file)
@@ -213,7 +213,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
                                                 addr_beg_p - ib_ptr,
                                                 addr_end_p - addr_beg_p,
                                                 exp);
-                       else if (nf_ct_expect_related(exp) != 0) {
+                       else if (nf_ct_expect_related(exp, 0) != 0) {
                                nf_ct_helper_log(skb, ct,
                                                 "cannot add expectation");
                                ret = NF_DROP;
index 1b77444..6aa01eb 100644 (file)
@@ -2616,7 +2616,7 @@ ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
        if (IS_ERR(exp))
                return PTR_ERR(exp);
 
-       err = nf_ct_expect_related_report(exp, portid, report);
+       err = nf_ct_expect_related_report(exp, portid, report, 0);
        nf_ct_expect_put(exp);
        return err;
 }
@@ -3367,7 +3367,7 @@ ctnetlink_create_expect(struct net *net,
                goto err_rcu;
        }
 
-       err = nf_ct_expect_related_report(exp, portid, report);
+       err = nf_ct_expect_related_report(exp, portid, report, 0);
        nf_ct_expect_put(exp);
 err_rcu:
        rcu_read_unlock();
index b22042a..a971183 100644 (file)
@@ -234,9 +234,9 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
        nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre);
        if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK)
                nf_nat_pptp_exp_gre(exp_orig, exp_reply);
-       if (nf_ct_expect_related(exp_orig) != 0)
+       if (nf_ct_expect_related(exp_orig, 0) != 0)
                goto out_put_both;
-       if (nf_ct_expect_related(exp_reply) != 0)
+       if (nf_ct_expect_related(exp_reply, 0) != 0)
                goto out_unexpect_orig;
 
        /* Add GRE keymap entries */
index c2eb365..5b05487 100644 (file)
@@ -1,7 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * ip_conntrack_proto_gre.c - Version 3.0
- *
  * Connection tracking protocol helper module for GRE.
  *
  * GRE is a generic encapsulation protocol, which is generally not very
index dd53e2b..097deba 100644 (file)
@@ -215,7 +215,7 @@ int nf_conntrack_icmpv4_error(struct nf_conn *tmpl,
                return -NF_ACCEPT;
        }
 
-       /* See ip_conntrack_proto_tcp.c */
+       /* See nf_conntrack_proto_tcp.c */
        if (state->net->ct.sysctl_checksum &&
            state->hook == NF_INET_PRE_ROUTING &&
            nf_ip_checksum(skb, state->hook, dataoff, IPPROTO_ICMP)) {
index d5fdfa0..85c1f8c 100644 (file)
@@ -472,6 +472,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
        struct ip_ct_tcp_state *receiver = &state->seen[!dir];
        const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
        __u32 seq, ack, sack, end, win, swin;
+       u16 win_raw;
        s32 receiver_offset;
        bool res, in_recv_win;
 
@@ -480,7 +481,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
         */
        seq = ntohl(tcph->seq);
        ack = sack = ntohl(tcph->ack_seq);
-       win = ntohs(tcph->window);
+       win_raw = ntohs(tcph->window);
+       win = win_raw;
        end = segment_seq_plus_len(seq, skb->len, dataoff, tcph);
 
        if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
@@ -655,14 +657,14 @@ static bool tcp_in_window(const struct nf_conn *ct,
                            && state->last_seq == seq
                            && state->last_ack == ack
                            && state->last_end == end
-                           && state->last_win == win)
+                           && state->last_win == win_raw)
                                state->retrans++;
                        else {
                                state->last_dir = dir;
                                state->last_seq = seq;
                                state->last_ack = ack;
                                state->last_end = end;
-                               state->last_win = win;
+                               state->last_win = win_raw;
                                state->retrans = 0;
                        }
                }
index 81448c3..1aebd65 100644 (file)
@@ -153,7 +153,7 @@ static int help(struct sk_buff *skb,
        nf_ct_dump_tuple(&exp->tuple);
 
        /* Can't expect this?  Best to drop packet now. */
-       if (nf_ct_expect_related(exp) != 0) {
+       if (nf_ct_expect_related(exp, 0) != 0) {
                nf_ct_helper_log(skb, ct, "cannot add expectation");
                ret = NF_DROP;
        }
index 1072517..b83dc9b 100644 (file)
@@ -977,11 +977,15 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff,
                /* -EALREADY handling works around end-points that send
                 * SDP messages with identical port but different media type,
                 * we pretend expectation was set up.
+                * It also works in the case that SDP messages are sent with
+                * identical expect tuples but for different master conntracks.
                 */
-               int errp = nf_ct_expect_related(rtp_exp);
+               int errp = nf_ct_expect_related(rtp_exp,
+                                               NF_CT_EXP_F_SKIP_MASTER);
 
                if (errp == 0 || errp == -EALREADY) {
-                       int errcp = nf_ct_expect_related(rtcp_exp);
+                       int errcp = nf_ct_expect_related(rtcp_exp,
+                                               NF_CT_EXP_F_SKIP_MASTER);
 
                        if (errcp == 0 || errcp == -EALREADY)
                                ret = NF_ACCEPT;
@@ -1296,7 +1300,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
                ret = hooks->expect(skb, protoff, dataoff, dptr, datalen,
                                    exp, matchoff, matchlen);
        else {
-               if (nf_ct_expect_related(exp) != 0) {
+               if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                } else
index df6d6d6..80ee53f 100644 (file)
@@ -78,7 +78,7 @@ static int tftp_help(struct sk_buff *skb,
                nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
                if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
                        ret = nf_nat_tftp(skb, ctinfo, exp);
-               else if (nf_ct_expect_related(exp) != 0) {
+               else if (nf_ct_expect_related(exp, 0) != 0) {
                        nf_ct_helper_log(skb, ct, "cannot add expectation");
                        ret = NF_DROP;
                }
index a352604..3bc7e08 100644 (file)
@@ -48,7 +48,7 @@ static unsigned int help(struct sk_buff *skb,
                int res;
 
                exp->tuple.dst.u.tcp.port = htons(port);
-               res = nf_ct_expect_related(exp);
+               res = nf_ct_expect_related(exp, 0);
                if (res == 0)
                        break;
                else if (res != -EBUSY) {
index 9ab4104..3f6023e 100644 (file)
@@ -519,7 +519,7 @@ another_round:
  * and NF_INET_LOCAL_OUT, we change the destination to map into the
  * range. It might not be possible to get a unique tuple, but we try.
  * At worst (or if we race), we will end up with a final duplicate in
- * __ip_conntrack_confirm and drop the packet. */
+ * __nf_conntrack_confirm and drop the packet. */
 static void
 get_unique_tuple(struct nf_conntrack_tuple *tuple,
                 const struct nf_conntrack_tuple *orig_tuple,
index d48484a..aace676 100644 (file)
@@ -91,7 +91,7 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
index dfb7ef8..c691ab8 100644 (file)
@@ -53,7 +53,7 @@ static unsigned int help(struct sk_buff *skb,
                int ret;
 
                exp->tuple.dst.u.tcp.port = htons(port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, 0);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
index e338d91..f0a735e 100644 (file)
@@ -414,7 +414,7 @@ static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff,
                int ret;
 
                exp->tuple.dst.u.udp.port = htons(port);
-               ret = nf_ct_expect_related(exp);
+               ret = nf_ct_expect_related(exp, NF_CT_EXP_F_SKIP_MASTER);
                if (ret == 0)
                        break;
                else if (ret != -EBUSY) {
@@ -607,7 +607,8 @@ static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
                int ret;
 
                rtp_exp->tuple.dst.u.udp.port = htons(port);
-               ret = nf_ct_expect_related(rtp_exp);
+               ret = nf_ct_expect_related(rtp_exp,
+                                          NF_CT_EXP_F_SKIP_MASTER);
                if (ret == -EBUSY)
                        continue;
                else if (ret < 0) {
@@ -615,7 +616,8 @@ static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff,
                        break;
                }
                rtcp_exp->tuple.dst.u.udp.port = htons(port + 1);
-               ret = nf_ct_expect_related(rtcp_exp);
+               ret = nf_ct_expect_related(rtcp_exp,
+                                          NF_CT_EXP_F_SKIP_MASTER);
                if (ret == 0)
                        break;
                else if (ret == -EBUSY) {
index 833a11f..1a59113 100644 (file)
@@ -30,7 +30,7 @@ static unsigned int help(struct sk_buff *skb,
                = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
        exp->dir = IP_CT_DIR_REPLY;
        exp->expectfn = nf_nat_follow_master;
-       if (nf_ct_expect_related(exp) != 0) {
+       if (nf_ct_expect_related(exp, 0) != 0) {
                nf_ct_helper_log(skb, exp->master, "cannot add expectation");
                return NF_DROP;
        }
index b101f18..c769462 100644 (file)
@@ -470,7 +470,7 @@ synproxy_send_client_synack(struct net *net,
        struct iphdr *iph, *niph;
        struct tcphdr *nth;
        unsigned int tcp_hdr_size;
-       u16 mss = opts->mss;
+       u16 mss = opts->mss_encode;
 
        iph = ip_hdr(skb);
 
@@ -687,7 +687,7 @@ ipv4_synproxy_hook(void *priv, struct sk_buff *skb,
        state = &ct->proto.tcp;
        switch (state->state) {
        case TCP_CONNTRACK_CLOSE:
-               if (th->rst && !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
+               if (th->rst && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
                        nf_ct_seqadj_init(ct, ctinfo, synproxy->isn -
                                                      ntohl(th->seq) + 1);
                        break;
@@ -884,7 +884,7 @@ synproxy_send_client_synack_ipv6(struct net *net,
        struct ipv6hdr *iph, *niph;
        struct tcphdr *nth;
        unsigned int tcp_hdr_size;
-       u16 mss = opts->mss;
+       u16 mss = opts->mss_encode;
 
        iph = ipv6_hdr(skb);
 
@@ -1111,7 +1111,7 @@ ipv6_synproxy_hook(void *priv, struct sk_buff *skb,
        state = &ct->proto.tcp;
        switch (state->state) {
        case TCP_CONNTRACK_CLOSE:
-               if (th->rst && !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
+               if (th->rst && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
                        nf_ct_seqadj_init(ct, ctinfo, synproxy->isn -
                                                      ntohl(th->seq) + 1);
                        break;
index ed17a7c..605a7cf 100644 (file)
@@ -1662,7 +1662,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
 
                chain->flags |= NFT_BASE_CHAIN | flags;
                basechain->policy = NF_ACCEPT;
-               INIT_LIST_HEAD(&basechain->cb_list);
+               flow_block_init(&basechain->flow_block);
        } else {
                chain = kzalloc(sizeof(*chain), GFP_KERNEL);
                if (chain == NULL)
@@ -1900,6 +1900,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
 
        if (nla[NFTA_CHAIN_FLAGS])
                flags = ntohl(nla_get_be32(nla[NFTA_CHAIN_FLAGS]));
+       else if (chain)
+               flags = chain->flags;
 
        nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
 
index 2c33028..64f5fd5 100644 (file)
@@ -116,7 +116,7 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain,
        struct flow_block_cb *block_cb;
        int err;
 
-       list_for_each_entry(block_cb, &basechain->cb_list, list) {
+       list_for_each_entry(block_cb, &basechain->flow_block.cb_list, list) {
                err = block_cb->cb(type, type_data, block_cb->cb_priv);
                if (err < 0)
                        return err;
@@ -154,7 +154,7 @@ static int nft_flow_offload_rule(struct nft_trans *trans,
 static int nft_flow_offload_bind(struct flow_block_offload *bo,
                                 struct nft_base_chain *basechain)
 {
-       list_splice(&bo->cb_list, &basechain->cb_list);
+       list_splice(&bo->cb_list, &basechain->flow_block.cb_list);
        return 0;
 }
 
@@ -198,6 +198,7 @@ static int nft_flow_offload_chain(struct nft_trans *trans,
                return -EOPNOTSUPP;
 
        bo.command = cmd;
+       bo.block = &basechain->flow_block;
        bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
        bo.extack = &extack;
        INIT_LIST_HEAD(&bo.cb_list);
index 92077d4..4abbb45 100644 (file)
@@ -578,7 +578,7 @@ static int nfnetlink_bind(struct net *net, int group)
        ss = nfnetlink_get_subsys(type << 8);
        rcu_read_unlock();
        if (!ss)
-               request_module("nfnetlink-subsys-%d", type);
+               request_module_nowait("nfnetlink-subsys-%d", type);
        return 0;
 }
 #endif
index 3fd540b..b5d5d07 100644 (file)
@@ -193,7 +193,7 @@ static inline void nft_chain_filter_inet_init(void) {}
 static inline void nft_chain_filter_inet_fini(void) {}
 #endif /* CONFIG_NF_TABLES_IPV6 */
 
-#ifdef CONFIG_NF_TABLES_BRIDGE
+#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE)
 static unsigned int
 nft_do_chain_bridge(void *priv,
                    struct sk_buff *skb,
index 2f89bde..ff9ac8a 100644 (file)
@@ -142,3 +142,6 @@ MODULE_ALIAS_NFT_CHAIN(AF_INET, "nat");
 #ifdef CONFIG_NF_TABLES_IPV6
 MODULE_ALIAS_NFT_CHAIN(AF_INET6, "nat");
 #endif
+#ifdef CONFIG_NF_TABLES_INET
+MODULE_ALIAS_NFT_CHAIN(1, "nat");      /* NFPROTO_INET */
+#endif
index 827ab61..46ca8bc 100644 (file)
@@ -1252,7 +1252,7 @@ static void nft_ct_expect_obj_eval(struct nft_object *obj,
                          priv->l4proto, NULL, &priv->dport);
        exp->timeout.expires = jiffies + priv->timeout * HZ;
 
-       if (nf_ct_expect_related(exp) != 0)
+       if (nf_ct_expect_related(exp, 0) != 0)
                regs->verdict.code = NF_DROP;
 }
 
index fe93e73..b836d55 100644 (file)
@@ -129,7 +129,7 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
        priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
 
        priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
-       if (priv->modulus <= 1)
+       if (priv->modulus < 1)
                return -ERANGE;
 
        if (priv->offset + priv->modulus - 1 < priv->offset)
index 76866f7..f69afb9 100644 (file)
@@ -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)
@@ -546,7 +538,7 @@ nft_meta_select_ops(const struct nft_ctx *ctx,
        if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
                return ERR_PTR(-EINVAL);
 
-#ifdef CONFIG_NF_TABLES_BRIDGE
+#if IS_ENABLED(CONFIG_NF_TABLES_BRIDGE) && IS_MODULE(CONFIG_NFT_BRIDGE_META)
        if (ctx->family == NFPROTO_BRIDGE)
                return ERR_PTR(-EAGAIN);
 #endif
index 8487eef..43eeb1f 100644 (file)
@@ -291,4 +291,4 @@ module_exit(nft_redir_module_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo@debian.org>");
-MODULE_ALIAS_NFT_EXPR("nat");
+MODULE_ALIAS_NFT_EXPR("redir");
index 80060ad..928e661 100644 (file)
@@ -31,6 +31,8 @@ static void nft_synproxy_tcp_options(struct synproxy_options *opts,
                opts->options |= NF_SYNPROXY_OPT_ECN;
 
        opts->options &= priv->info.options;
+       opts->mss_encode = opts->mss;
+       opts->mss = info->mss;
        if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP)
                synproxy_init_timestamp_cookie(info, opts);
        else
index 96740d3..c4f54ad 100644 (file)
@@ -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;
index 892287d..d01410e 100644 (file)
@@ -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;
index dca3b1e..bc89e16 100644 (file)
@@ -59,7 +59,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
 void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
                           const struct sk_buff *skb)
 {
-       struct flow_stats *stats;
+       struct sw_flow_stats *stats;
        unsigned int cpu = smp_processor_id();
        int len = skb->len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
 
@@ -87,7 +87,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
                        if (likely(flow->stats_last_writer != -1) &&
                            likely(!rcu_access_pointer(flow->stats[cpu]))) {
                                /* Try to allocate CPU-specific stats. */
-                               struct flow_stats *new_stats;
+                               struct sw_flow_stats *new_stats;
 
                                new_stats =
                                        kmem_cache_alloc_node(flow_stats_cache,
@@ -134,7 +134,7 @@ void ovs_flow_stats_get(const struct sw_flow *flow,
 
        /* We open code this to make sure cpu 0 is always considered */
        for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) {
-               struct flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]);
+               struct sw_flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]);
 
                if (stats) {
                        /* Local CPU may write on non-local stats, so we must
@@ -158,7 +158,7 @@ void ovs_flow_stats_clear(struct sw_flow *flow)
 
        /* We open code this to make sure cpu 0 is always considered */
        for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) {
-               struct flow_stats *stats = ovsl_dereference(flow->stats[cpu]);
+               struct sw_flow_stats *stats = ovsl_dereference(flow->stats[cpu]);
 
                if (stats) {
                        spin_lock_bh(&stats->lock);
index 3e2cc22..a5506e2 100644 (file)
@@ -194,7 +194,7 @@ struct sw_flow_actions {
        struct nlattr actions[];
 };
 
-struct flow_stats {
+struct sw_flow_stats {
        u64 packet_count;               /* Number of packets matched. */
        u64 byte_count;                 /* Number of bytes matched. */
        unsigned long used;             /* Last used time (in jiffies). */
@@ -216,7 +216,7 @@ struct sw_flow {
        struct cpumask cpu_used_mask;
        struct sw_flow_mask *mask;
        struct sw_flow_actions __rcu *sf_acts;
-       struct flow_stats __rcu *stats[]; /* One for each CPU.  First one
+       struct sw_flow_stats __rcu *stats[]; /* One for each CPU.  First one
                                           * is allocated at flow creation time,
                                           * the rest are allocated on demand
                                           * while holding the 'stats[0].lock'.
index 988fd8a..cf3582c 100644 (file)
@@ -66,7 +66,7 @@ void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
 struct sw_flow *ovs_flow_alloc(void)
 {
        struct sw_flow *flow;
-       struct flow_stats *stats;
+       struct sw_flow_stats *stats;
 
        flow = kmem_cache_zalloc(flow_cache, GFP_KERNEL);
        if (!flow)
@@ -110,7 +110,7 @@ static void flow_free(struct sw_flow *flow)
        for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask))
                if (flow->stats[cpu])
                        kmem_cache_free(flow_stats_cache,
-                                       (struct flow_stats __force *)flow->stats[cpu]);
+                                       (struct sw_flow_stats __force *)flow->stats[cpu]);
        kmem_cache_free(flow_cache, flow);
 }
 
@@ -712,13 +712,13 @@ int ovs_flow_init(void)
 
        flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow)
                                       + (nr_cpu_ids
-                                         * sizeof(struct flow_stats *)),
+                                         * sizeof(struct sw_flow_stats *)),
                                       0, 0, NULL);
        if (flow_cache == NULL)
                return -ENOMEM;
 
        flow_stats_cache
-               = kmem_cache_create("sw_flow_stats", sizeof(struct flow_stats),
+               = kmem_cache_create("sw_flow_stats", sizeof(struct sw_flow_stats),
                                    0, SLAB_HWCACHE_ALIGN, NULL);
        if (flow_stats_cache == NULL) {
                kmem_cache_destroy(flow_cache);
index ff74c4b..9986d60 100644 (file)
@@ -105,7 +105,8 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id,
                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 +138,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);
index 80335b4..822f453 100644 (file)
@@ -1061,6 +1061,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
index 9f2f45c..7666ec7 100644 (file)
@@ -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);
index 9d3ce81..9c3ac96 100644 (file)
@@ -436,6 +436,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.
  */
index 5d3f33c..bae1443 100644 (file)
@@ -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);
index 8126b26..fd1f7e7 100644 (file)
@@ -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;
                }
 
index ce36b0f..32ac04d 100644 (file)
@@ -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;
                }
 
index 621fb22..9b92882 100644 (file)
@@ -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;
index b501ce0..33a1a74 100644 (file)
@@ -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;
index 10eb2bb..06ef74b 100644 (file)
@@ -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;
index b2380c5..8f0140c 100644 (file)
@@ -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;
index 41d5398..92ee853 100644 (file)
@@ -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;
                }
index 055faa2..be3f88d 100644 (file)
@@ -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;
index ca2597c..0f299e3 100644 (file)
@@ -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;
                }
 
index 45923eb..7b858c1 100644 (file)
@@ -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;
index 45e9d6b..17360c6 100644 (file)
@@ -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;
index a065f62..49cec3e 100644 (file)
@@ -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;
index 274d7a0..595308d 100644 (file)
@@ -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;
index f28ddba..33aefa2 100644 (file)
@@ -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;
                }
 
index 215a067..b100870 100644 (file)
@@ -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;
                }
 
index 4f07706..7da3518 100644 (file)
@@ -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;
                }
 
index 10dffda..6d0debd 100644 (file)
@@ -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;
 }
 
index 9269d35..a3c9eea 100644 (file)
@@ -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),
 };
index d144233..efd3cfb 100644 (file)
@@ -691,6 +691,8 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
        if (!indr_dev->block)
                return;
 
+       bo.block = &indr_dev->block->flow_block;
+
        indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
                          &bo);
        tcf_block_setup(indr_dev->block, &bo);
@@ -775,6 +777,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
                .command        = command,
                .binder_type    = ei->binder_type,
                .net            = dev_net(dev),
+               .block          = &block->flow_block,
                .block_shared   = tcf_block_shared(block),
                .extack         = extack,
        };
@@ -810,6 +813,7 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
        bo.net = dev_net(dev);
        bo.command = command;
        bo.binder_type = ei->binder_type;
+       bo.block = &block->flow_block;
        bo.block_shared = tcf_block_shared(block);
        bo.extack = extack;
        INIT_LIST_HEAD(&bo.cb_list);
@@ -987,8 +991,8 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
                return ERR_PTR(-ENOMEM);
        }
        mutex_init(&block->lock);
+       flow_block_init(&block->flow_block);
        INIT_LIST_HEAD(&block->chain_list);
-       INIT_LIST_HEAD(&block->cb_list);
        INIT_LIST_HEAD(&block->owner_list);
        INIT_LIST_HEAD(&block->chain0.filter_chain_list);
 
@@ -1514,7 +1518,7 @@ void tcf_block_put(struct tcf_block *block)
 EXPORT_SYMBOL(tcf_block_put);
 
 static int
-tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
+tcf_block_playback_offloads(struct tcf_block *block, flow_setup_cb_t *cb,
                            void *cb_priv, bool add, bool offload_in_use,
                            struct netlink_ext_ack *extack)
 {
@@ -1570,7 +1574,7 @@ static int tcf_block_bind(struct tcf_block *block,
 
                i++;
        }
-       list_splice(&bo->cb_list, &block->cb_list);
+       list_splice(&bo->cb_list, &block->flow_block.cb_list);
 
        return 0;
 
@@ -2152,7 +2156,9 @@ replay:
                tfilter_notify(net, skb, n, tp, block, q, parent, fh,
                               RTM_NEWTFILTER, false, rtnl_held);
                tfilter_put(tp, fh);
-               q->flags &= ~TCQ_F_CAN_BYPASS;
+               /* q pointer is NULL for shared blocks */
+               if (q)
+                       q->flags &= ~TCQ_F_CAN_BYPASS;
        }
 
 errout:
@@ -3156,7 +3162,7 @@ int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
        if (block->nooffloaddevcnt && err_stop)
                return -EOPNOTSUPP;
 
-       list_for_each_entry(block_cb, &block->cb_list, list) {
+       list_for_each_entry(block_cb, &block->flow_block.cb_list, list) {
                err = block_cb->cb(type, type_data, block_cb->cb_priv);
                if (err) {
                        if (err_stop)
index 691f718..3f7a9c0 100644 (file)
@@ -651,7 +651,7 @@ skip:
        }
 }
 
-static int cls_bpf_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int cls_bpf_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                             void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct cls_bpf_head *head = rtnl_dereference(tp->root);
index 38d6e85..0541237 100644 (file)
@@ -1800,7 +1800,7 @@ fl_get_next_hw_filter(struct tcf_proto *tp, struct cls_fl_filter *f, bool add)
        return NULL;
 }
 
-static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int fl_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                        void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct tcf_block *block = tp->chain->block;
index a30d2f8..455ea27 100644 (file)
@@ -282,7 +282,7 @@ skip:
        arg->count++;
 }
 
-static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int mall_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                          void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
index be9e46c..8614088 100644 (file)
@@ -1152,7 +1152,7 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg,
 }
 
 static int u32_reoffload_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
-                              bool add, tc_setup_cb_t *cb, void *cb_priv,
+                              bool add, flow_setup_cb_t *cb, void *cb_priv,
                               struct netlink_ext_ack *extack)
 {
        struct tc_cls_u32_offload cls_u32 = {};
@@ -1172,7 +1172,7 @@ static int u32_reoffload_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
 }
 
 static int u32_reoffload_knode(struct tcf_proto *tp, struct tc_u_knode *n,
-                              bool add, tc_setup_cb_t *cb, void *cb_priv,
+                              bool add, flow_setup_cb_t *cb, void *cb_priv,
                               struct netlink_ext_ack *extack)
 {
        struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);
@@ -1213,7 +1213,7 @@ static int u32_reoffload_knode(struct tcf_proto *tp, struct tc_u_knode *n,
        return 0;
 }
 
-static int u32_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
+static int u32_reoffload(struct tcf_proto *tp, bool add, flow_setup_cb_t *cb,
                         void *cb_priv, struct netlink_ext_ack *extack)
 {
        struct tc_u_common *tp_c = tp->data;
index 25ef172..30169b3 100644 (file)
@@ -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;
 }
 
index aa80cda..9d1f83b 100644 (file)
@@ -985,7 +985,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 +1315,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. */
index 302e355..5b93258 100644 (file)
@@ -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);
index d86030e..e135d4e 100644 (file)
@@ -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;
index dd8537f..83ae41d 100644 (file)
@@ -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;
 }
index f345662..ca8ac96 100644 (file)
@@ -476,7 +476,7 @@ static void tipc_topsrv_accept(struct work_struct *work)
        }
 }
 
-/* tipc_toprsv_listener_data_ready - interrupt callback with connection request
+/* tipc_topsrv_listener_data_ready - interrupt callback with connection request
  * The queued job is launched into tipc_topsrv_accept()
  */
 static void tipc_topsrv_listener_data_ready(struct sock *sk)
index 4674e57..9cbbae6 100644 (file)
@@ -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,44 @@ 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;
+       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 +529,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 +542,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 +612,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 +770,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 +778,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 +789,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 +841,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)
index 53b4ad9..91d21b0 100644 (file)
@@ -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;
index f2084e3..9d864eb 100644 (file)
@@ -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
index 45d9afc..32b3c71 100644 (file)
@@ -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))
index fc83dd1..fd05ae1 100644 (file)
@@ -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);
index 1c39d6a..d0e35b7 100644 (file)
@@ -1697,7 +1697,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 +1719,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 +2072,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);
index 96b3b1b..eb26421 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Simple pci display device.
  *
index 77c742f..4b0432e 100644 (file)
@@ -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
index 8a5c4d6..4bbf4fc 100644 (file)
@@ -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
index 0d434d0..2f66ed3 100644 (file)
@@ -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.
 # ---------------------------------------------------------------------------
index 5241d07..41c50f9 100644 (file)
@@ -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))
 
index 6b19c1a..26e6574 100644 (file)
 # 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)
index 7915823..c458696 100755 (executable)
@@ -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():
index 47f6f3e..bbaf293 100755 (executable)
@@ -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
index 1134892..3569d2d 100644 (file)
@@ -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);
index a7124f8..915775e 100755 (executable)
@@ -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
index f230e65..3b638c0 100755 (executable)
@@ -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();
 
index a1ffe2e..af4c979 100644 (file)
@@ -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
index 624ccc6..f8efaa9 100644 (file)
@@ -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;
 }
 
index e63a90f..1f0a6ea 100644 (file)
@@ -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);
index 7b977b7..7985dd8 100644 (file)
@@ -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,
index 99b8821..41905af 100644 (file)
@@ -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;
index 860543a..703857a 100644 (file)
@@ -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);
index 0d35359..0ecafd0 100644 (file)
@@ -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);
 
index 1192c75..3c2db38 100644 (file)
@@ -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");
index e30e86c..51f10ed 100644 (file)
@@ -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
index c8d1b43..48d8637 100644 (file)
@@ -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
index baa1537..f2a6df5 100644 (file)
@@ -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 */
index cb8b094..a6d8c0d 100644 (file)
@@ -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,9 @@ 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 Stoney */
        { PCI_DEVICE(0x1022, 0x157a),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
index 4f8d084..f299f13 100644 (file)
@@ -1083,6 +1083,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),
index a4ade6b..bc4dfaf 100644 (file)
@@ -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;
 }
 
index 6203f54..5b049fc 100644 (file)
@@ -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,
 };
 
index 6f0e28f..16313b9 100644 (file)
 #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);
index 528695c..8c601a3 100644 (file)
@@ -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));
index f6a37aa..a59e513 100644 (file)
 #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)
index cdc8314..abcdeb9 100644 (file)
@@ -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");
index f6f19fa..3b79734 100644 (file)
@@ -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");
index 32b26f1..b235806 100644 (file)
@@ -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");
index 75931c9..18d51e5 100644 (file)
@@ -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
index 5605b66..0a6ff13 100644 (file)
@@ -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,
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 30a4e83..288df24 100644 (file)
@@ -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,
index ac8678f..556b1a7 100644 (file)
@@ -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);
 
index e5cde0d..ef84915 100644 (file)
@@ -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);
 
index fac09be..4661233 100644 (file)
@@ -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"),
index 229e395..4a5adae 100644 (file)
@@ -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.
  *
index b94b482..1cc801b 100644 (file)
@@ -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.
  */
index b7f11f6..d0fb43c 100644 (file)
@@ -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.
  */
index c36c0aa..771b0ef 100644 (file)
@@ -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.
  *
index 616eb09..60dea35 100644 (file)
@@ -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.
  *
index 68ae43f..cc972d2 100644 (file)
@@ -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.
  *
  */
 
index d27853e..34eb0ba 100644 (file)
@@ -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.
  */
index 0b430b9..3897766 100644 (file)
@@ -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.
  *
index 4b33105..e200baa 100644 (file)
@@ -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.
  *
index 0c9c0ed..42fa40a 100644 (file)
@@ -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.
  *
index f60a719..ac75838 100644 (file)
@@ -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");
 
index 0a34d0e..88ebaf6 100644 (file)
@@ -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;
        }
 
index c5fc246..782e534 100644 (file)
@@ -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 |
index dfb6e46..f0f5fa9 100644 (file)
@@ -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;
 }
 
index fd6eaae..44f899b 100644 (file)
@@ -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)
index f013b24..2790c00 100644 (file)
@@ -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);
 }
 
index f2b3929..ffd8d43 100644 (file)
@@ -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 */
index 50244b8..2ecba91 100644 (file)
@@ -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 */
index 9b22329..7fa5c61 100644 (file)
@@ -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,
index ac59b50..bc7bf15 100644 (file)
@@ -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,
index b730d97..90d118c 100644 (file)
@@ -275,7 +275,8 @@ retry:
                                goto retry;
                        }
                        spin_unlock(&sound_loader_lock);
-                       return -EBUSY;
+                       r = -EBUSY;
+                       goto fail;
                }
        }
 
index 71d5f54..4c12cc5 100644 (file)
@@ -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;
 }
index 14fc1e1..c406497 100644 (file)
@@ -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;
 }
index f0662bd..27bf61c 100644 (file)
@@ -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,
index 0d24c72..ed158f0 100644 (file)
@@ -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");
index 7ee9d17..e852c7f 100644 (file)
@@ -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;
index 4602464..a4217c1 100644 (file)
@@ -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
index d819a3e..9a50771 100644 (file)
@@ -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)
index f33105b..8601d82 100644 (file)
@@ -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
index 38920ee..7b94dcc 100644 (file)
@@ -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
index d6ab5b4..503d3f4 100644 (file)
@@ -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 */
index d213ec5..f0b0c90 100644 (file)
 
 #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 */
index abd238d..63b1f50 100644 (file)
 #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
  */
index 36c197f..406f771 100644 (file)
@@ -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 */
index a87904d..1be0e79 100644 (file)
@@ -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
index 661d73f..8a5b2f8 100644 (file)
@@ -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;
index 3a73f53..328d05e 100644 (file)
@@ -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
index 7d113a9..4a8c02c 100644 (file)
@@ -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 */
index c2152f3..5e3f12d 100644 (file)
@@ -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)
index ed4ee17..b3105ac 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _UAPI_LINUX_SCHED_H
 #define _UAPI_LINUX_SCHED_H
 
+#include <linux/types.h>
+
 /*
  * cloning flags:
  */
 #define CLONE_NEWNET           0x40000000      /* New network namespace */
 #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_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 */
index 964e872..78efe87 100644 (file)
@@ -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 */
index 467224f..d821107 100644 (file)
@@ -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__"
index 03748a7..bae8879 100644 (file)
 
 #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)
index 794dd50..2586b6c 100644 (file)
@@ -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>
@@ -612,10 +613,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 +1378,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 +1506,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;
        }
@@ -4507,13 +4519,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;
index 5007b5d..680e630 100644 (file)
@@ -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);
index 5f26620..176f2f0 100644 (file)
@@ -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;
index b881faf..6d875ca 100644 (file)
@@ -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;
index 6d148a4..adc5a7e 100644 (file)
@@ -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 \
index d4e2e18..caaab28 100644 (file)
@@ -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::
index 5f54feb..d030c87 100644 (file)
@@ -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,
 
index a19690a..c8c86a0 100644 (file)
@@ -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);
+}
index b4e6f9e..c29976e 100644 (file)
 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
index a640ca7..513cb2f 100644 (file)
@@ -379,8 +379,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;
index 66d5a66..0193128 100644 (file)
@@ -173,7 +173,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);
index 6418782..3d0ffd4 100644 (file)
@@ -698,6 +698,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;
                }
index 8f24865..0140ddb 100644 (file)
@@ -1059,7 +1059,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);
index b55a534..352cf39 100644 (file)
@@ -607,7 +607,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)
+               perf_evlist__close(evsel_list);
 
        return WEXITSTATUS(status);
 }
@@ -1997,6 +2003,7 @@ int cmd_stat(int argc, const char **argv)
                        perf_session__write_header(perf_stat.session, evsel_list, fd, true);
                }
 
+               perf_evlist__close(evsel_list);
                perf_session__delete(perf_stat.session);
        }
 
index 1a91a19..d413761 100644 (file)
@@ -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},
 };
index 930b80f..aa597ae 100755 (executable)
@@ -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"
index f80c51d..d227d74 100644 (file)
@@ -1,7 +1,8 @@
 // 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 "../perf.h"
 #include "libslang.h"
 #include "ui.h"
 #include "util.h"
@@ -14,7 +15,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>
 
index bc134b8..5a24dd3 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/kernel.h>
-#include "../cache.h"
+#include "../../util/cache.h"
 #include "../progress.h"
 #include "../libslang.h"
 #include "../ui.h"
index ac9ad23..1635367 100644 (file)
@@ -1122,7 +1122,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;
 
index 3acfbe3..39cce66 100644 (file)
@@ -751,7 +751,10 @@ size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
        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;
index ebb46da..52459dd 100644 (file)
@@ -1291,6 +1291,7 @@ static void perf_evsel__free_id(struct perf_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)
@@ -2077,6 +2078,7 @@ void perf_evsel__close(struct perf_evsel *evsel)
 
        perf_evsel__close_fd(evsel);
        perf_evsel__free_fd(evsel);
+       perf_evsel__free_id(evsel);
 }
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
index c24db7f..1903d7e 100644 (file)
@@ -3559,6 +3559,13 @@ 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);
 
@@ -3639,7 +3646,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;
@@ -3747,7 +3754,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))
index cf826ec..83b2fbb 100644 (file)
@@ -1378,6 +1378,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 +1390,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);
index f70ab98..7aa38da 100644 (file)
@@ -222,7 +222,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);
 
index cd1eb73..8394d48 100644 (file)
@@ -2230,6 +2230,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
                        field = next;
                }
        }
+       pev->nargs = 0;
        zfree(&pev->args);
 }
 
index d0fd6c6..37efa1f 100644 (file)
@@ -36,10 +36,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,10 +53,10 @@ 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;
        }
@@ -61,7 +67,7 @@ static int perf_session__process_compressed_event(struct perf_session *session,
        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;
        }
@@ -255,15 +261,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);
 }
 
index dd8920b..863dbad 100644 (file)
@@ -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[];
index 656065a..accb1bf 100644 (file)
@@ -819,7 +819,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)) {
index 173f337..4efde78 100644 (file)
@@ -92,6 +92,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 +223,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 */
index 12755b4..183f630 100644 (file)
@@ -288,6 +288,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);
index 873ab50..590793c 100644 (file)
@@ -214,14 +214,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;
 }
 
index 23bdb98..d220239 100644 (file)
@@ -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;
index 495066b..ded7a95 100644 (file)
@@ -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)
index 7252542..6fd8649 100755 (executable)
@@ -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";
index 11c9c62..c085964 100644 (file)
@@ -57,7 +57,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 \
index 5aeaa28..a680628 100644 (file)
@@ -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);
index 51a3a31..bb8b0da 100755 (executable)
@@ -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 (executable)
index 0000000..c515326
--- /dev/null
@@ -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 (executable)
index 0000000..5cf7ce1
--- /dev/null
@@ -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
index b0fda28..d438193 100644 (file)
        .result = ACCEPT,
        .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 = {
index 4c22326..bdb6959 100644 (file)
@@ -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;
                }
index 71231ad..47315fe 100755 (executable)
@@ -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"
index 0a76314..8b944cf 100755 (executable)
@@ -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"
index ec15c4f..0ac49d9 100644 (file)
@@ -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 {
index 41266af..b35da37 100644 (file)
@@ -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 (file)
index 0000000..63ed533
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_KVM=y
+CONFIG_KVM_INTEL=y
+CONFIG_KVM_AMD=y
index 3019544..79b0aff 100644 (file)
@@ -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"
 
index 4ce0bc1..c7cced7 100644 (file)
@@ -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
index cca2baa..a8d8e8b 100755 (executable)
@@ -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))
index 090fff9..4c285b6 100644 (file)
 #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;
index 7eaa8a3..b632965 100644 (file)
@@ -339,13 +339,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",
index cc7c7d7..6503b1c 100644 (file)
         "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": []
     }
 ]
index 4602326..a4f4d4c 100644 (file)
@@ -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;
        }
index aa316d9..1fb6abe 100644 (file)
@@ -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
index f645c0f..35a0698 100644 (file)
@@ -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);
 
index 254c5f1..ccf1fde 100644 (file)
@@ -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);
        }
index 3dd8238..362a018 100644 (file)
@@ -214,6 +214,20 @@ static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
        kvm_pmu_release_perf_event(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);
 }
index 936962a..c45e2d7 100644 (file)
@@ -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++) {
index 3ba7278..44efc2f 100644 (file)
@@ -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);
 
index 6dd5ad7..96aab77 100644 (file)
@@ -484,10 +484,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);
 }
index c2c9ce0..0c653a1 100644 (file)
@@ -662,12 +662,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);
 
index 04786c8..13d4b38 100644 (file)
@@ -919,6 +919,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;
index 57205be..797e050 100644 (file)
@@ -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);
index 887f3b0..c6a91b0 100644 (file)
@@ -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);